bug 10561: intermidiate checkin for FirewallRuleFeature

1) Added new apis: createFirewallRule, deleteFirewallRule, listFirewallRules
2) Modified existing apis - added boolean openFirewall parameter to createPortForwardingRule/createIpForwardingRule/createRemoteAccessVpn. If parameter is set to true, open firewall on the domR before creating an actual PF rule there
Modified backend calls appropriately.
3) Schema changes for firewall_rules table:
* startPort/endPort can be null now
* added icmp_type, icmp_code fields (can be not null only when protocol is icmp)
4) Added new manager - FirewallManagerImpl

Conflicts:

	api/src/com/cloud/api/BaseCmd.java
	client/tomcatconf/commands.properties.in
	server/src/com/cloud/api/ApiResponseHelper.java
	server/src/com/cloud/configuration/DefaultComponentLibrary.java
	server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
	server/src/com/cloud/network/rules/RulesManagerImpl.java
This commit is contained in:
alena 2011-08-09 15:20:20 -07:00
parent adfb6a1f03
commit 6b9603bc4c
49 changed files with 1764 additions and 487 deletions

View File

@ -17,6 +17,9 @@
*/
package com.cloud.agent.api.to;
import java.util.ArrayList;
import java.util.List;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.State;
import com.cloud.utils.net.NetUtils;
@ -53,10 +56,25 @@ public class FirewallRuleTO {
protected FirewallRuleTO() {
}
public FirewallRuleTO(long id, String srcIp, String protocol, int srcPortStart, int srcPortEnd, boolean revoked, boolean alreadyAdded, FirewallRule.Purpose purpose) {
public FirewallRuleTO(long id, String srcIp, String protocol, Integer srcPortStart, Integer srcPortEnd, boolean revoked, boolean alreadyAdded, FirewallRule.Purpose purpose) {
this.srcIp = srcIp;
this.protocol = protocol;
this.srcPortRange = new int[] {srcPortStart, srcPortEnd};
if (srcPortStart != null) {
List<Integer> portRange = new ArrayList<Integer>();
portRange.add(srcPortStart);
if (srcPortEnd != null) {
portRange.add(srcPortEnd);
}
srcPortRange = new int[portRange.size()];
int i = 0;
for (Integer port : portRange) {
srcPortRange[i] = port.intValue();
i ++;
}
}
this.revoked = revoked;
this.alreadyAdded = alreadyAdded;
this.purpose = purpose;

View File

@ -254,4 +254,5 @@ public class ApiConstants {
public static final String REDUNDANT_ROUTER = "redundantrouter";
public static final String IP_NETWORK_LIST = "iptonetworklist";
public static final String KEYBOARD="keyboard";
public static final String OPEN_FIREWALL="openfirewall";
}

View File

@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
<<<<<<< HEAD
import org.apache.log4j.Logger;
@ -56,6 +57,39 @@ import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.vm.BareMetalVmService;
import com.cloud.vm.UserVmService;
=======
import org.apache.log4j.Logger;
import com.cloud.configuration.ConfigurationService;
import com.cloud.consoleproxy.ConsoleProxyService;
import com.cloud.dao.EntityManager;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.NetworkService;
import com.cloud.network.VirtualNetworkApplianceService;
import com.cloud.network.firewall.FirewallService;
import com.cloud.network.lb.LoadBalancingRulesService;
import com.cloud.network.rules.RulesService;
import com.cloud.network.security.SecurityGroupService;
import com.cloud.network.vpn.RemoteAccessVpnService;
import com.cloud.resource.ResourceService;
import com.cloud.server.ManagementService;
import com.cloud.storage.StorageService;
import com.cloud.storage.snapshot.SnapshotService;
import com.cloud.template.TemplateService;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.UserContext;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.vm.UserVmService;
import com.cloud.vm.BareMetalVmService;
>>>>>>> 32445e6... bug 10561: intermidiate checkin for FirewallRuleFeature
public abstract class BaseCmd {
private static final Logger s_logger = Logger.getLogger(BaseCmd.class.getName());
@ -117,7 +151,8 @@ public abstract class BaseCmd {
public static LoadBalancingRulesService _lbService;
public static RemoteAccessVpnService _ravService;
public static BareMetalVmService _bareMetalVmService;
public static ProjectService _projectService;
public static ProjectService _projectService;
public static FirewallService _firewallService;
static void setComponents(ResponseGenerator generator) {
ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name);
@ -139,7 +174,8 @@ public abstract class BaseCmd {
_ravService = locator.getManager(RemoteAccessVpnService.class);
_responseGenerator = generator;
_bareMetalVmService = locator.getManager(BareMetalVmService.class);
_projectService = locator.getManager(ProjectService.class);
_projectService = locator.getManager(ProjectService.class);
_firewallService = locator.getManager(FirewallService.class);
}
public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException;

View File

@ -32,6 +32,7 @@ import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.DomainRouterResponse;
import com.cloud.api.response.EventResponse;
import com.cloud.api.response.ExtractResponse;
import com.cloud.api.response.FirewallResponse;
import com.cloud.api.response.FirewallRuleResponse;
import com.cloud.api.response.HostResponse;
import com.cloud.api.response.IPAddressResponse;
@ -76,6 +77,7 @@ import com.cloud.network.Network;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.VpnUser;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNatRule;
@ -207,5 +209,7 @@ public interface ResponseGenerator {
List<TemplateResponse> createIsoResponses(VirtualMachineTemplate iso, long zoneId, boolean readyOnly);
List<TemplateResponse> createTemplateResponses(long templateId, Long vmId);
FirewallResponse createFirewallResponse(FirewallRule fwRule);
}

View File

@ -0,0 +1,283 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseAsyncCreateCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.FirewallResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.rules.FirewallRule;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.utils.net.NetUtils;
@Implementation(description = "Creates a firewall rule for a given ip address", responseObject = FirewallResponse.class)
public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule {
public static final Logger s_logger = Logger.getLogger(CreateFirewallRuleCmd.class.getName());
private static final String s_name = "createfirewallruleresponse";
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.LONG, required = true, description = "the IP address id of the port forwarding rule")
private Long ipAddressId;
@Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = "the protocol for the firewall rule. Valid values are TCP/UDP/ICMP.")
private String protocol;
@Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "the starting port of firewall rule")
private Integer publicStartPort;
@Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "the ending port of firewall rule")
private Integer publicEndPort;
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
private List<String> cidrlist;
@Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent")
private Integer icmpType;
@Parameter(name = ApiConstants.ICMP_CODE, type = CommandType.INTEGER, description = "error code for this icmp message")
private Integer icmpCode;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public Long getIpAddressId() {
return ipAddressId;
}
@Override
public String getProtocol() {
return protocol.trim();
}
public List<String> getSourceCidrList() {
if (cidrlist != null) {
return cidrlist;
} else {
List<String> oneCidrList = new ArrayList<String>();
oneCidrList.add(NetUtils.ALL_CIDRS);
return oneCidrList;
}
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public void setSourceCidrList(List<String> cidrs){
cidrlist = cidrs;
}
@Override
public void execute() throws ResourceUnavailableException {
UserContext callerContext = UserContext.current();
boolean success = false;
FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId());
try {
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
success = _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller());
// State is different after the rule is applied, so get new object here
rule = _entityMgr.findById(FirewallRule.class, getEntityId());
FirewallResponse fwResponse = new FirewallResponse();
if (rule != null) {
fwResponse = _responseGenerator.createFirewallResponse(rule);
setResponseObject(fwResponse);
}
fwResponse.setResponseName(getCommandName());
} finally {
if (!success || rule == null) {
_firewallService.revokeFirewallRule(getEntityId(), true);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create firewall rule");
}
}
}
@Override
public long getId() {
throw new UnsupportedOperationException("database id can only provided by VO objects");
}
@Override
public String getXid() {
// FIXME: We should allow for end user to specify Xid.
return null;
}
@Override
public long getSourceIpAddressId() {
return ipAddressId;
}
@Override
public Integer getSourcePortStart() {
if (publicStartPort != null) {
return publicStartPort.intValue();
}
return null;
}
@Override
public Integer getSourcePortEnd() {
if (publicEndPort == null) {
if (publicStartPort != null) {
return publicStartPort.intValue();
}
} else {
return publicEndPort.intValue();
}
return null;
}
@Override
public Purpose getPurpose() {
return Purpose.Firewall;
}
@Override
public State getState() {
throw new UnsupportedOperationException("Should never call me to find the state");
}
@Override
public long getNetworkId() {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public long getEntityOwnerId() {
Account account = UserContext.current().getCaller();
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public long getDomainId() {
IpAddress ip = _networkService.getIp(ipAddressId);
return ip.getDomainId();
}
@Override
public void create() {
if (getSourceCidrList() != null) {
for (String cidr: getSourceCidrList()){
if (!NetUtils.isValidCIDR(cidr)){
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Source cidrs formatting error " + cidr);
}
}
}
try {
FirewallRule result = _firewallService.createFirewallRule(this);
setEntityId(result.getId());
} catch (NetworkRuleConflictException ex) {
s_logger.info("Network rule conflict: " + ex.getMessage());
s_logger.trace("Network Rule Conflict: ", ex);
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_FIREWALL_OPEN;
}
@Override
public String getEventDescription() {
IpAddress ip = _networkService.getIp(ipAddressId);
return ("Createing firewall rule for Ip: " + ip.getAddress() + " for protocol:" + this.getProtocol());
}
@Override
public long getAccountId() {
IpAddress ip = _networkService.getIp(ipAddressId);
return ip.getAccountId();
}
@Override
public String getSyncObjType() {
return BaseAsyncCmd.networkSyncObject;
}
@Override
public Long getSyncObjId() {
return getIp().getAssociatedWithNetworkId();
}
private IpAddress getIp() {
IpAddress ip = _networkService.getIp(ipAddressId);
if (ip == null) {
throw new InvalidParameterValueException("Unable to find ip address by id " + ipAddressId);
}
return ip;
}
@Override
public Integer getIcmpCode() {
if (icmpCode != null) {
return icmpCode;
} else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
return -1;
}
return null;
}
@Override
public Integer getIcmpType() {
if (icmpType != null) {
return icmpType;
} else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
return -1;
}
return null;
}
}

View File

@ -18,6 +18,8 @@
package com.cloud.api.commands;
import java.util.List;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
@ -61,6 +63,9 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
@Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING, required=true, description="the protocol for the rule. Valid values are TCP or UDP.")
private String protocol;
@Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN, description = "if true, firewall rule for source/end pubic port is automatically created; if false - firewall rule has to be created explicitely. Has value true by default")
private Boolean openFirewall;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -77,6 +82,14 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
public int getEndPort() {
return endPort;
}
public Boolean getOpenFirewall() {
if (openFirewall != null) {
return openFirewall;
} else {
return true;
}
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
@ -89,11 +102,16 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
@Override
public void execute() throws ResourceUnavailableException{
boolean result = false;
boolean result = true;
FirewallRule rule = null;
try {
UserContext.current().setEventDetails("Rule Id: "+ getEntityId());
result = _rulesService.applyStaticNatRules(ipAddressId, UserContext.current().getCaller());
if (getOpenFirewall()) {
result = result && _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), UserContext.current().getCaller());
}
result = result && _rulesService.applyStaticNatRules(ipAddressId, UserContext.current().getCaller());
rule = _entityMgr.findById(FirewallRule.class, getEntityId());
StaticNatRule staticNatRule = _rulesService.buildStaticNatRule(rule);
IpForwardingRuleResponse fwResponse = _responseGenerator.createIpForwardingRuleResponse(staticNatRule);
@ -111,7 +129,7 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
public void create() {
StaticNatRule rule;
try {
rule = _rulesService.createStaticNatRule(this);
rule = _rulesService.createStaticNatRule(this, getOpenFirewall());
} catch (NetworkRuleConflictException e) {
s_logger.info("Unable to create Static Nat Rule due to " + e.getMessage());
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage());
@ -167,12 +185,12 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
}
@Override
public int getSourcePortStart() {
public Integer getSourcePortStart() {
return startPort;
}
@Override
public int getSourcePortEnd() {
public Integer getSourcePortEnd() {
if (endPort == null) {
return startPort;
} else {
@ -235,4 +253,19 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
}
return ip;
}
@Override
public Integer getIcmpCode() {
return null;
}
@Override
public Integer getIcmpType() {
return null;
}
@Override
public List<String> getSourceCidrList() {
return null;
}
}

View File

@ -27,7 +27,6 @@ import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.LoadBalancerResponse;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
@ -65,6 +64,9 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
private List<String> cidrlist;
@Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN, description = "if true, firewall rule for source/end pubic port is automatically created; if false - firewall rule has to be created explicitely. Has value true by default")
private Boolean openFirewall;
/////////////////////////////////////////////////////
@ -109,6 +111,14 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
public List<String> getSourceCidrList() {
return cidrlist;
}
public Boolean getOpenFirewall() {
if (openFirewall != null) {
return openFirewall;
} else {
return true;
}
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
@ -131,7 +141,7 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
LoadBalancer result = null;
try {
result = _lbService.createLoadBalancerRule(this);
result = _lbService.createLoadBalancerRule(this, getOpenFirewall());
} catch (NetworkRuleConflictException e) {
s_logger.warn("Exception: ", e);
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage());
@ -158,12 +168,12 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
}
@Override
public int getSourcePortStart() {
public Integer getSourcePortStart() {
return publicPort.intValue();
}
@Override
public int getSourcePortEnd() {
public Integer getSourcePortEnd() {
return publicPort.intValue();
}
@ -210,5 +220,16 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
@Override
public long getEntityOwnerId() {
return getAccountId();
}
}
@Override
public Integer getIcmpCode() {
return null;
}
@Override
public Integer getIcmpType() {
return null;
}
}

View File

@ -29,7 +29,6 @@ import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.FirewallRuleResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
@ -75,6 +74,9 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
private List<String> cidrlist;
@Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN, description = "if true, firewall rule for source/end pubic port is automatically created; if false - firewall rule has to be created explicitely. Has value true by default")
private Boolean openFirewall;
// ///////////////////////////////////////////////////
@ -98,6 +100,14 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
public List<String> getSourceCidrList() {
return cidrlist;
}
public Boolean getOpenFirewall() {
if (openFirewall != null) {
return openFirewall;
} else {
return true;
}
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
@ -115,11 +125,16 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
@Override
public void execute() throws ResourceUnavailableException {
UserContext callerContext = UserContext.current();
boolean success = false;
boolean success = true;
PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, getEntityId());
try {
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
success = _rulesService.applyPortForwardingRules(rule.getSourceIpAddressId(), callerContext.getCaller());
if (getOpenFirewall()) {
success = success && _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller());
}
success = success && _rulesService.applyPortForwardingRules(rule.getSourceIpAddressId(), callerContext.getCaller());
// State is different after the rule is applied, so get new object here
rule = _entityMgr.findById(PortForwardingRule.class, getEntityId());
@ -154,12 +169,12 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
}
@Override
public int getSourcePortStart() {
public Integer getSourcePortStart() {
return publicStartPort.intValue();
}
@Override
public int getSourcePortEnd() {
public Integer getSourcePortEnd() {
return (publicEndPort == null)? publicStartPort.intValue() : publicEndPort.intValue();
}
@ -219,7 +234,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
}
}
try {
PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId);
PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, getOpenFirewall());
setEntityId(result.getId());
} catch (NetworkRuleConflictException ex) {
s_logger.info("Network rule conflict: " + ex.getMessage());
@ -262,5 +277,15 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
}
return ip;
}
@Override
public Integer getIcmpCode() {
return null;
}
@Override
public Integer getIcmpType() {
return null;
}
}

View File

@ -27,6 +27,7 @@ import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
@ -58,6 +59,9 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
@Parameter(name="domainid", type=CommandType.LONG, description="an optional domainId for the VPN. If the account parameter is used, domainId must also be used.")
private Long domainId;
@Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN, description = "if true, firewall rule for source/end pubic port is automatically created; if false - firewall rule has to be created explicitely. Has value true by default")
private Boolean openFirewall;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -82,13 +86,20 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
this.ipRange = ipRange;
}
public Boolean getOpenFirewall() {
if (openFirewall != null) {
return openFirewall;
} else {
return true;
}
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
@Override
public String getCommandName() {
return s_name;
}
@ -125,7 +136,7 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
@Override
public void create() {
try {
RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange);
RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall());
if (vpn != null) {
this.setEntityId(vpn.getServerAddressId());
} else {
@ -141,7 +152,7 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
@Override
public void execute(){
try {
RemoteAccessVpn result = _ravService.startRemoteAccessVpn(publicIpId);
RemoteAccessVpn result = _ravService.startRemoteAccessVpn(publicIpId, getOpenFirewall());
if (result != null) {
RemoteAccessVpnResponse response = _responseGenerator.createRemoteAccessVpnResponse(result);
response.setResponseName(getCommandName());

View File

@ -0,0 +1,112 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.SuccessResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.rules.FirewallRule;
import com.cloud.user.UserContext;
@Implementation(description="Deletes a firewall rule", responseObject=SuccessResponse.class)
public class DeleteFirewallRuleCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteFirewallRuleCmd.class.getName());
private static final String s_name = "deletefirewallruleresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the firewall rule")
private Long id;
// unexposed parameter needed for events logging
@Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.LONG, expose=false)
private Long ownerId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public String getEventType() {
return EventTypes.EVENT_FIREWALL_CLOSE;
}
@Override
public String getEventDescription() {
return ("Deleting firewall rule id=" + id);
}
@Override
public long getEntityOwnerId() {
if (ownerId == null) {
FirewallRule rule = _entityMgr.findById(FirewallRule.class, id);
if (rule == null) {
throw new InvalidParameterValueException("Unable to find firewall rule by id=" + id);
} else {
ownerId = _entityMgr.findById(FirewallRule.class, id).getAccountId();
}
}
return ownerId;
}
@Override
public void execute() throws ResourceUnavailableException {
UserContext.current().setEventDetails("Rule Id: " + id);
boolean result = _firewallService.revokeFirewallRule(id, true);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete firewall rule");
}
}
@Override
public String getSyncObjType() {
return BaseAsyncCmd.networkSyncObject;
}
@Override
public Long getSyncObjId() {
return _firewallService.getFirewallRule(id).getNetworkId();
}
}

View File

@ -0,0 +1,98 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.response.FirewallResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.network.rules.FirewallRule;
@Implementation(description="Lists all firewall rules for an IP address.", responseObject=FirewallResponse.class)
public class ListFirewallRulesCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger(ListPortForwardingRulesCmd.class.getName());
private static final String s_name = "listfirewallrulesresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, description="Lists rule with the specified ID.")
private Long id;
@Parameter(name=ApiConstants.IP_ADDRESS_ID, type=CommandType.LONG, description="the id of IP address of the firwall services")
private Long ipAddressId;
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="account. Must be used with the domainId parameter.")
private String accountName;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the domain ID. If used with the account parameter, lists port forwarding rules for the specified account in this domain.")
private Long domainId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public Long getIpAddressId() {
return ipAddressId;
}
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
List<? extends FirewallRule> result = _firewallService.listFirewallRules(this);
ListResponse<FirewallResponse> response = new ListResponse<FirewallResponse>();
List<FirewallResponse> fwResponses = new ArrayList<FirewallResponse>();
for (FirewallRule fwRule : result) {
FirewallResponse ruleData = _responseGenerator.createFirewallResponse(fwRule);
ruleData.setObjectName("firewallrule");
fwResponses.add(ruleData);
}
response.setResponses(fwResponses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
}

View File

@ -0,0 +1,97 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.response;
import com.cloud.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class FirewallResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="the ID of the firewall rule")
private Long id;
@SerializedName(ApiConstants.PROTOCOL) @Param(description="the protocol of the firewall rule")
private String protocol;
@SerializedName(ApiConstants.START_PORT) @Param(description="the starting port of firewall rule's port range")
private String startPort;
@SerializedName(ApiConstants.END_PORT) @Param(description = "the ending port of firewall rule's port range")
private String endPort;
@SerializedName(ApiConstants.IP_ADDRESS_ID) @Param(description="the public ip address id for the port forwarding rule")
private Long publicIpAddressId;
@SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the public ip address for the port forwarding rule")
private String publicIpAddress;
@SerializedName(ApiConstants.STATE) @Param(description="the state of the rule")
private String state;
@SerializedName(ApiConstants.CIDR_LIST) @Param(description="the cidr list to forward traffic from")
private String cidrList;
@SerializedName(ApiConstants.ICMP_TYPE) @Param(description= "type of the icmp message being sent")
private Integer icmpType;
@SerializedName(ApiConstants.ICMP_CODE) @Param(description = "error code for this icmp message")
private Integer icmpCode;
public void setId(Long id) {
this.id = id;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public void setStartPort(String startPort) {
this.startPort = startPort;
}
public void setEndPort(String endPort) {
this.endPort = endPort;
}
public void setPublicIpAddressId(Long publicIpAddressId) {
this.publicIpAddressId = publicIpAddressId;
}
public void setPublicIpAddress(String publicIpAddress) {
this.publicIpAddress = publicIpAddress;
}
public void setState(String state) {
this.state = state;
}
public void setCidrList(String cidrList) {
this.cidrList = cidrList;
}
public void setIcmpType(Integer icmpType) {
this.icmpType = icmpType;
}
public void setIcmpCode(Integer icmpCode) {
this.icmpCode = icmpCode;
}
}

View File

@ -18,8 +18,6 @@
package com.cloud.api.response;
import com.cloud.api.ApiConstants;
import com.cloud.api.Parameter;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;

View File

@ -61,6 +61,8 @@ public class EventTypes {
public static final String EVENT_NETWORK_CREATE = "NETWORK.CREATE";
public static final String EVENT_NETWORK_DELETE = "NETWORK.DELETE";
public static final String EVENT_NETWORK_UPDATE = "NETWORK.UPDATE";
public static final String EVENT_FIREWALL_OPEN = "FIREWALL.OPEN";
public static final String EVENT_FIREWALL_CLOSE = "FIREWALL.CLOSE";
// Load Balancers
public static final String EVENT_ASSIGN_TO_LOAD_BALANCER_RULE = "LB.ASSIGN.TO.RULE";

View File

@ -0,0 +1,25 @@
package com.cloud.network.firewall;
import java.util.List;
import com.cloud.api.commands.ListFirewallRulesCmd;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.rules.FirewallRule;
import com.cloud.user.Account;
public interface FirewallService {
FirewallRule createFirewallRule(FirewallRule rule) throws NetworkRuleConflictException;
List<? extends FirewallRule> listFirewallRules(ListFirewallRulesCmd cmd);
/**
* Revokes a firewall rule
* @param ruleId the id of the rule to revoke.
* @return
*/
boolean revokeFirewallRule(long ruleId, boolean apply);
boolean applyFirewallRules(long ipId, Account caller) throws ResourceUnavailableException;
FirewallRule getFirewallRule(long ruleId);
}

View File

@ -88,12 +88,12 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer{
}
@Override
public int getSourcePortStart() {
public Integer getSourcePortStart() {
return lb.getSourcePortStart();
}
@Override
public int getSourcePortEnd() {
public Integer getSourcePortEnd() {
return lb.getSourcePortEnd();
}
@ -159,4 +159,14 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer{
return revoked;
}
}
@Override
public Integer getIcmpCode() {
return null;
}
@Override
public Integer getIcmpType() {
return null;
}
}

View File

@ -30,10 +30,11 @@ import com.cloud.uservm.UserVm;
public interface LoadBalancingRulesService {
/**
* Create a load balancer rule from the given ipAddress/port to the given private port
* @param openFirewall TODO
* @param cmd the command specifying the ip address, public port, protocol, private port, and algorithm
* @return the newly created LoadBalancerVO if successful, null otherwise
*/
LoadBalancer createLoadBalancerRule(LoadBalancer lb) throws NetworkRuleConflictException;
LoadBalancer createLoadBalancerRule(LoadBalancer lb, boolean openFirewall) throws NetworkRuleConflictException;
LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd);

View File

@ -17,6 +17,8 @@
*/
package com.cloud.network.rules;
import java.util.List;
import com.cloud.acl.ControlledEntity;
public interface FirewallRule extends ControlledEntity {
@ -48,12 +50,12 @@ public interface FirewallRule extends ControlledEntity {
/**
* @return first port of the source port range.
*/
int getSourcePortStart();
Integer getSourcePortStart();
/**
* @return last port of the source prot range. If this is null, that means only one port is mapped.
*/
int getSourcePortEnd();
Integer getSourcePortEnd();
/**
* @return protocol to open these ports for.
@ -67,4 +69,10 @@ public interface FirewallRule extends ControlledEntity {
long getNetworkId();
long getSourceIpAddressId();
Integer getIcmpCode();
Integer getIcmpType();
List<String> getSourceCidrList();
}

View File

@ -35,6 +35,4 @@ public interface LoadBalancer extends FirewallRule {
String getAlgorithm();
public List<String> getSourceCidrList();
}

View File

@ -17,8 +17,6 @@
*/
package com.cloud.network.rules;
import java.util.List;
import com.cloud.utils.net.Ip;
/**
@ -45,8 +43,4 @@ public interface PortForwardingRule extends FirewallRule {
*/
long getVirtualMachineId();
/**
* @return source cidr to forward
*/
List<String> getSourceCidrList();
}

View File

@ -32,10 +32,11 @@ public interface RulesService {
* an ip address and a virtual machine.
* @param rule rule to be created.
* @param vmId vm to be linked to. If specified the destination ip address is ignored.
* @param openFirewall TODO
* @return PortForwardingRule if created.
* @throws NetworkRuleConflictException if conflicts in the network rules are detected.
*/
PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId) throws NetworkRuleConflictException;
PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean openFirewall) throws NetworkRuleConflictException;
/**
* Revokes a port forwarding rule
@ -60,7 +61,7 @@ public interface RulesService {
PortForwardingRule getPortForwardigRule(long ruleId);
FirewallRule getFirewallRule(long ruleId);
StaticNatRule createStaticNatRule(StaticNatRule rule) throws NetworkRuleConflictException;
StaticNatRule createStaticNatRule(StaticNatRule rule, boolean openFirewall) throws NetworkRuleConflictException;
boolean revokeStaticNatRule(long ruleId, boolean apply);
@ -69,5 +70,5 @@ public interface RulesService {
StaticNatRule buildStaticNatRule(FirewallRule rule);
List<String> getSourceCidrs(long ruleId);
}

View File

@ -28,9 +28,9 @@ public interface StaticNatRule extends ControlledEntity, FirewallRule{
String getProtocol();
int getSourcePortStart();
Integer getSourcePortStart();
int getSourcePortEnd();
Integer getSourcePortEnd();
Purpose getPurpose();

View File

@ -28,9 +28,9 @@ import com.cloud.network.VpnUser;
public interface RemoteAccessVpnService {
RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange) throws NetworkRuleConflictException;
RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall) throws NetworkRuleConflictException;
void destroyRemoteAccessVpn(long vpnServerAddressId) throws ResourceUnavailableException;
RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId) throws ResourceUnavailableException;
RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException;
VpnUser addVpnUser(long vpnOwnerId, String userName, String password);
boolean removeVpnUser(long vpnOwnerId, String userName);

View File

@ -262,8 +262,14 @@ registerSSHKeyPair=com.cloud.api.commands.RegisterSSHKeyPairCmd;15
createSSHKeyPair=com.cloud.api.commands.CreateSSHKeyPairCmd;15
deleteSSHKeyPair=com.cloud.api.commands.DeleteSSHKeyPairCmd;15
listSSHKeyPairs=com.cloud.api.commands.ListSSHKeyPairsCmd;15
#### Projects commands
createProject=com.cloud.api.commands.CreateProjectCmd;15
deleteProject=com.cloud.api.commands.DeleteProjectCmd;15
listProjects=com.cloud.api.commands.ListProjectsCmd;15
listProjects=com.cloud.api.commands.ListProjectsCmd;15
####
createFirewallRule=com.cloud.api.commands.CreateFirewallRuleCmd;15
deleteFirewallRule=com.cloud.api.commands.DeleteFirewallRuleCmd;15
listFirewallRules=com.cloud.api.commands.ListFirewallRulesCmd;15

View File

@ -134,12 +134,14 @@ import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetFirewallRulesAnswer;
import com.cloud.agent.api.routing.SetFirewallRulesCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer;
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesAnswer;
@ -154,8 +156,8 @@ 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.LoadBalancerTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
import com.cloud.agent.api.to.StaticNatRuleTO;
@ -496,6 +498,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return execute((UpdateHostPasswordCommand)cmd);
} else if (cmd instanceof CheckRouterCommand) {
return execute((CheckRouterCommand)cmd);
} else if (cmd instanceof SetFirewallRulesCommand) {
return execute((SetFirewallRulesCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -6504,4 +6508,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return new Answer(cmd, success, "");
}
protected SetFirewallRulesAnswer execute(SetFirewallRulesCommand cmd) {
Connection conn = getConnection();
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
String[] results = new String[cmd.getRules().length];
int i = 0;
for (FirewallRuleTO rule : cmd.getRules()) {
//FIXME - Jana, add implementation here
}
return new SetFirewallRulesAnswer(cmd, results);
}
}

View File

@ -592,7 +592,7 @@ public class ApiDBUtils {
return _consoleProxyDao.findById(id);
}
public static List<String> findPortForwardingSourceCidrs(long id){
public static List<String> findFirewallSourceCidrs(long id){
return _firewallCidrsDao.getSourceCidrs(id);
}

View File

@ -44,6 +44,7 @@ import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.DomainRouterResponse;
import com.cloud.api.response.EventResponse;
import com.cloud.api.response.ExtractResponse;
import com.cloud.api.response.FirewallResponse;
import com.cloud.api.response.FirewallRuleResponse;
import com.cloud.api.response.HostResponse;
import com.cloud.api.response.IPAddressResponse;
@ -720,7 +721,7 @@ public class ApiResponseHelper implements ResponseGenerator {
lbResponse.setId(loadBalancer.getId());
lbResponse.setName(loadBalancer.getName());
lbResponse.setDescription(loadBalancer.getDescription());
List<String> cidrs = ApiDBUtils.findPortForwardingSourceCidrs(loadBalancer.getId());
List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(loadBalancer.getId());
lbResponse.setCidrList(StringUtils.join(cidrs, ","));
IPAddressVO publicIp = ApiDBUtils.findIpAddressById(loadBalancer.getSourceIpAddressId());
@ -989,7 +990,7 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setProtocol(fwRule.getProtocol());
response.setPublicStartPort(Integer.toString(fwRule.getSourcePortStart()));
response.setPublicEndPort(Integer.toString(fwRule.getSourcePortEnd()));
List<String> cidrs = ApiDBUtils.findPortForwardingSourceCidrs(fwRule.getId());
List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
response.setCidrList(StringUtils.join(cidrs, ","));
IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
@ -2147,4 +2148,37 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setObjectName("project");
return response;
}
public FirewallResponse createFirewallResponse(FirewallRule fwRule) {
FirewallResponse response = new FirewallResponse();
response.setId(fwRule.getId());
response.setProtocol(fwRule.getProtocol());
if (fwRule.getSourcePortStart() != null) {
response.setStartPort(Integer.toString(fwRule.getSourcePortStart()));
}
if (fwRule.getSourcePortEnd() != null) {
response.setEndPort(Integer.toString(fwRule.getSourcePortEnd()));
}
List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
response.setCidrList(StringUtils.join(cidrs, ","));
IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
response.setPublicIpAddressId(ip.getId());
response.setPublicIpAddress(ip.getAddress().addr());
FirewallRule.State state = fwRule.getState();
String stateToSet = state.toString();
if (state.equals(FirewallRule.State.Revoke)) {
stateToSet = "Deleting";
}
response.setIcmpCode(fwRule.getIcmpCode());
response.setIcmpType(fwRule.getIcmpType());
response.setState(stateToSet);
response.setObjectName("firewallrule");
return response;
}
}

View File

@ -82,6 +82,7 @@ import com.cloud.network.dao.NetworkDomainDaoImpl;
import com.cloud.network.dao.NetworkRuleConfigDaoImpl;
import com.cloud.network.dao.RemoteAccessVpnDaoImpl;
import com.cloud.network.dao.VpnUserDaoImpl;
import com.cloud.network.firewall.FirewallManagerImpl;
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
import com.cloud.network.ovs.OvsNetworkManagerImpl;
import com.cloud.network.ovs.OvsTunnelManagerImpl;
@ -316,6 +317,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
addManager("ClusterFenceManager", ClusterFenceManagerImpl.class);
addManager("ResourceManager", ResourceManagerImpl.class);
addManager("OCFS2Manager", OCFS2ManagerImpl.class);
addManager("FirewallManager", FirewallManagerImpl.class);
ComponentInfo<? extends Manager> info = addManager("ConsoleProxyManager", ConsoleProxyManagerImpl.class);
info.addParameter("consoleproxy.sslEnabled", "true");
addManager("ClusteredAgentManager", ClusteredAgentManagerImpl.class);

View File

@ -53,13 +53,13 @@ public class FirewallRulesCidrsVO {
public long getFirewallRuleId() {
return firewallRuleId;
}
public void setFirewallRuleId(long firewallRuleId){
this.firewallRuleId = firewallRuleId;
}
public String getCidr() {
return sourceCidrList;
}
public String getSourceCidrList() {
return sourceCidrList;
}
}

View File

@ -18,7 +18,6 @@
package com.cloud.network;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
@ -26,7 +25,6 @@ import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.LoadBalancer;
@ -52,21 +50,17 @@ public class LoadBalancerVO extends FirewallRuleVO implements LoadBalancer {
@Column(name="default_port_end")
private int defaultPortEnd;
@Transient
List<String> sourceCidrs;
public LoadBalancerVO() {
}
public LoadBalancerVO(String xId, String name, String description, long srcIpId, int srcPort, int dstPort, List<String> sourceCidrs, String algorithm, long networkId, long accountId, long domainId) {
super(xId, srcIpId, srcPort, NetUtils.TCP_PROTO, networkId, accountId, domainId, Purpose.LoadBalancing);
super(xId, srcIpId, srcPort, NetUtils.TCP_PROTO, networkId, accountId, domainId, Purpose.LoadBalancing, sourceCidrs, null, null);
this.name = name;
this.description = description;
this.algorithm = algorithm;
this.defaultPortStart = dstPort;
this.defaultPortEnd = dstPort;
this.sourceCidrs = sourceCidrs;
}
@Override
@ -77,14 +71,6 @@ public class LoadBalancerVO extends FirewallRuleVO implements LoadBalancer {
@Override
public String getDescription() {
return description;
}
public void setSourceCidrList(List<String> sourceCidrs) {
this.sourceCidrs=sourceCidrs;
}
@Override
public List<String> getSourceCidrList() {
return sourceCidrs;
}
@Override

View File

@ -94,13 +94,17 @@ import com.cloud.network.Networks.AddressFormat;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.RulesManager;
import com.cloud.network.vpn.PasswordResetElement;
import com.cloud.network.vpn.RemoteAccessVpnElement;
@ -214,6 +218,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
NetworkDomainDao _networkDomainDao;
@Inject
VMInstanceDao _vmDao;
@Inject
FirewallManager _firewallMgr;
@Inject
FirewallRulesDao _firewallDao;
@Inject DomainRouterDao _routerDao;
@ -2207,6 +2215,20 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
success = false;
s_logger.warn("Failed to cleanup LB rules as a part of network id=" + networkId + " cleanup");
}
//revoke all firewall rules for the network
try {
if (_firewallMgr.revokeAllFirewallRulesForNetwork(networkId, callerUserId, caller)) {
s_logger.debug("Successfully cleaned up firewallRules rules for network id=" + networkId);
} else {
success = false;
s_logger.warn("Failed to cleanup Firewall rules as a part of network id=" + networkId + " cleanup");
}
} catch (ResourceUnavailableException ex) {
success = false;
// shouldn't even come here as network is being cleaned up after all network elements are shutdown
s_logger.warn("Failed to cleanup Firewall rules as a part of network id=" + networkId + " cleanup due to resourceUnavailable ", ex);
}
// release all ip addresses
List<IPAddressVO> ipsToRelease = _ipAddressDao.listByAssociatedNetwork(networkId, null);
@ -2399,6 +2421,13 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
s_logger.warn("Failed to apply ip addresses as a part of network id" + networkId + " restart");
success = false;
}
// 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");
success = false;
}
// apply port forwarding rules
if (!_rulesMgr.applyPortForwardingRulesForNetwork(networkId, false, caller)) {
@ -2423,7 +2452,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (vpnsToReapply != null) {
for (RemoteAccessVpn vpn : vpnsToReapply) {
// Start remote access vpn per ip
if (_vpnMgr.startRemoteAccessVpn(vpn.getServerAddressId()) == null) {
if (_vpnMgr.startRemoteAccessVpn(vpn.getServerAddressId(), false) == null) {
s_logger.warn("Failed to reapply vpn rules as a part of network id=" + networkId + " restart");
success = false;
}
@ -2767,9 +2796,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
private boolean cleanupIpResources(long ipId, long userId, Account caller) {
boolean success = true;
//Revoke all PF/Static nat rules for the ip
try {
s_logger.debug("Revoking all PF/StaticNat rules as a part of public IP id=" + ipId + " release...");
if (!_rulesMgr.revokeAllRulesForIp(ipId, userId, caller)) {
s_logger.debug("Revoking all " + Purpose.PortForwarding + "/" + Purpose.StaticNat + " rules as a part of public IP id=" + ipId + " release...");
if (!_rulesMgr.revokeAllPFAndStaticNatRulesForIp(ipId, userId, caller)) {
s_logger.warn("Unable to revoke all the port forwarding rules for ip id=" + ipId + " as a part of ip release");
success = false;
}
@ -2778,7 +2809,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
success = false;
}
s_logger.debug("Revoking all LB rules as a part of public IP id=" + ipId + " release...");
s_logger.debug("Revoking all " + Purpose.LoadBalancing + " rules as a part of public IP id=" + ipId + " release...");
if (!_lbMgr.removeAllLoadBalanacersForIp(ipId, caller, userId)) {
s_logger.warn("Unable to revoke all the load balancer rules for ip id=" + ipId + " as a part of ip release");
success = false;
@ -2795,6 +2826,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
s_logger.warn("Unable to destroy remote access vpn for ip id=" + ipId + " as a part of ip release", e);
success = false;
}
//Revoke all firewall rules for the ip
try {
s_logger.debug("Revoking all " + Purpose.Firewall + "rules as a part of public IP id=" + ipId + " release...");
if (!_firewallMgr.revokeFirewallRulesForIp(ipId, userId, caller)) {
s_logger.warn("Unable to revoke all the firewall rules for ip id=" + ipId + " as a part of ip release");
success = false;
}
} catch (ResourceUnavailableException e) {
s_logger.warn("Unable to revoke all firewall rules for ip id=" + ipId + " as a part of ip release", e);
success = false;
}
return success;
}

View File

@ -39,10 +39,12 @@ public interface FirewallRulesDao extends GenericDao<FirewallRuleVO, Long> {
boolean releasePorts(long ipAddressId, String protocol, FirewallRule.Purpose purpose, int[] ports);
List<? extends FirewallRule> listByIpAndPurpose(long ipAddressId, FirewallRule.Purpose purpose);
List<FirewallRuleVO> listByIpAndPurpose(long ipAddressId, FirewallRule.Purpose purpose);
List<FirewallRuleVO> listByNetworkAndPurpose(long networkId, FirewallRule.Purpose purpose);
List<FirewallRuleVO> listStaticNatByVmId(long vmId);
List<FirewallRuleVO> listByIpPurposeAndProtocolAndNotRevoked(long ipAddressId, Integer startPort, Integer endPort, String protocol, FirewallRule.Purpose purpose);
}

View File

@ -36,6 +36,7 @@ import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
@Local(value=FirewallRulesDao.class) @DB(txn=false)
public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> implements FirewallRulesDao {
@ -46,6 +47,8 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
protected final SearchBuilder<FirewallRuleVO> ReleaseSearch;
protected SearchBuilder<FirewallRuleVO> VmSearch;
protected final FirewallRulesCidrsDaoImpl _firewallRulesCidrsDao = ComponentLocator.inject(FirewallRulesCidrsDaoImpl.class);
protected FirewallRulesDaoImpl() {
super();
@ -64,6 +67,9 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
NotRevokedSearch.and("ipId", NotRevokedSearch.entity().getSourceIpAddressId(), Op.EQ);
NotRevokedSearch.and("state", NotRevokedSearch.entity().getState(), Op.NEQ);
NotRevokedSearch.and("purpose", NotRevokedSearch.entity().getPurpose(), Op.EQ);
NotRevokedSearch.and("protocol", NotRevokedSearch.entity().getProtocol(), Op.EQ);
NotRevokedSearch.and("sourcePortStart", NotRevokedSearch.entity().getSourcePortStart(), Op.EQ);
NotRevokedSearch.and("sourcePortEnd", NotRevokedSearch.entity().getSourcePortEnd(), Op.EQ);
NotRevokedSearch.and("networkId", NotRevokedSearch.entity().getNetworkId(), Op.EQ);
NotRevokedSearch.done();
@ -167,6 +173,49 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
sc.setParameters("purpose", Purpose.StaticNat);
sc.setJoinParameters("ipSearch", "associatedWithVmId", vmId);
return listBy(sc);
}
@Override @DB
public FirewallRuleVO persist(FirewallRuleVO firewallRule) {
Transaction txn = Transaction.currentTxn();
txn.start();
FirewallRuleVO dbfirewallRule = super.persist(firewallRule);
saveSourceCidrs(firewallRule);
txn.commit();
return dbfirewallRule;
}
public void saveSourceCidrs(FirewallRuleVO firewallRule) {
List<String> cidrlist = firewallRule.getSourceCidrList();
if (cidrlist == null) {
return;
}
_firewallRulesCidrsDao.persist(firewallRule.getId(), cidrlist);
}
@Override
public List<FirewallRuleVO> listByIpPurposeAndProtocolAndNotRevoked(long ipAddressId, Integer startPort, Integer endPort, String protocol, FirewallRule.Purpose purpose) {
SearchCriteria<FirewallRuleVO> sc = NotRevokedSearch.create();
sc.setParameters("ipId", ipAddressId);
sc.setParameters("state", State.Revoke);
if (purpose != null) {
sc.setParameters("purpose", purpose);
}
if (protocol != null) {
sc.setParameters("protocol", protocol);
}
sc.setParameters("sourcePortStart", startPort);
sc.setParameters("sourcePortEnd", endPort);
return listBy(sc);
}

View File

@ -28,9 +28,7 @@ import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@ -120,48 +118,5 @@ public class LoadBalancerDaoImpl extends GenericDaoBase<LoadBalancerVO, Long> im
sc.setParameters("name", name);
return findOneBy(sc);
}
public void saveSourceCidrs(LoadBalancerVO loadBalancerRule) {
List<String> cidrlist = loadBalancerRule.getSourceCidrList();
if (cidrlist == null) {
return;
}
_portForwardingRulesCidrsDao.persist(loadBalancerRule.getId(), cidrlist);
}
public void loadSourceCidrs(LoadBalancerVO loadBalancerRule){
List<String> sourceCidrs = _portForwardingRulesCidrsDao.getSourceCidrs(loadBalancerRule.getId());
loadBalancerRule.setSourceCidrList(sourceCidrs);
}
@Override @DB
public LoadBalancerVO persist(LoadBalancerVO loadBalancerRule) {
Transaction txn = Transaction.currentTxn();
txn.start();
LoadBalancerVO dbfirewallRule = super.persist(loadBalancerRule);
saveSourceCidrs(loadBalancerRule);
txn.commit();
return dbfirewallRule;
}
@Override @DB
public boolean update(Long loadBalancerRuleId, LoadBalancerVO loadBalancerRule) {
Transaction txn = Transaction.currentTxn();
txn.start();
boolean persisted = super.update(loadBalancerRuleId, loadBalancerRule);
if (!persisted) {
return persisted;
}
saveSourceCidrs(loadBalancerRule);
txn.commit();
return persisted;
}
}

View File

@ -267,7 +267,7 @@ public class VirtualRouterElement extends DhcpElement implements NetworkElement,
firewallCapabilities.put(Capability.PortForwarding, "true");
firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
firewallCapabilities.put(Capability.StaticNat, "true");
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp");
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
firewallCapabilities.put(Capability.MultipleIps, "true");
firewallCapabilities.put(Capability.SupportedSourceNatTypes, "per account");

View File

@ -0,0 +1,499 @@
package com.cloud.network.firewall;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.api.commands.ListFirewallRulesCmd;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
import com.cloud.network.dao.FirewallRulesCidrsDao;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRule.State;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.UserContext;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
@Local(value = { FirewallService.class, FirewallManager.class })
public class FirewallManagerImpl implements FirewallService, FirewallManager, Manager{
private static final Logger s_logger = Logger.getLogger(FirewallManagerImpl.class);
String _name;
@Inject
FirewallRulesDao _firewallDao;
@Inject
IPAddressDao _ipAddressDao;
@Inject
EventDao _eventDao;
@Inject
DomainDao _domainDao;
@Inject
FirewallRulesCidrsDao _firewallCidrsDao;
@Inject
AccountManager _accountMgr;
@Inject
NetworkManager _networkMgr;
@Inject
UsageEventDao _usageEventDao;
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
return true;
}
@Override
public FirewallRule createFirewallRule(FirewallRule rule) throws NetworkRuleConflictException {
Account caller = UserContext.current().getCaller();
return createFirewallRule(rule.getSourceIpAddressId(), caller, rule.getXid(), rule.getSourcePortStart() ,rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(), rule.getIcmpCode(), rule.getIcmpType());
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewll rule", create = true)
public FirewallRule createFirewallRule(long ipAddrId, Account caller, String xId, Integer portStart,Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType) throws NetworkRuleConflictException{
IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId);
// Validate ip address
if (ipAddress == null) {
throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " doesn't exist in the system");
} else if (ipAddress.isOneToOneNat()) {
throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " has static nat enabled");
}
validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol);
if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) {
throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only");
}
Long networkId = ipAddress.getAssociatedWithNetworkId();
Long accountId = ipAddress.getAccountId();
Long domainId = ipAddress.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);
newRule = _firewallDao.persist(newRule);
detectRulesConflict(newRule, ipAddress);
if (!_firewallDao.setStateToAdd(newRule)) {
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
}
UserContext.current().setEventDetails("Rule Id: " + newRule.getId());
txn.commit();
return newRule;
}
@Override
public List<? extends FirewallRule> listFirewallRules(ListFirewallRulesCmd cmd) {
Account caller = UserContext.current().getCaller();
Long ipId = cmd.getIpAddressId();
Long id = cmd.getId();
String path = null;
Pair<String, Long> accountDomainPair = _accountMgr.finalizeAccountDomainForList(caller, cmd.getAccountName(), cmd.getDomainId());
String accountName = accountDomainPair.first();
Long domainId = accountDomainPair.second();
if (ipId != null) {
IPAddressVO ipAddressVO = _ipAddressDao.findById(ipId);
if (ipAddressVO == null || !ipAddressVO.readyToUse()) {
throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for firewall rules yet");
}
_accountMgr.checkAccess(caller, ipAddressVO);
}
if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
Domain domain = _accountMgr.getDomain(caller.getDomainId());
path = domain.getPath();
}
Filter filter = new Filter(FirewallRuleVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchBuilder<FirewallRuleVO> sb = _firewallDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), Op.EQ);
sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), Op.EQ);
sb.and("domainId", sb.entity().getDomainId(), Op.EQ);
sb.and("purpose", sb.entity().getPurpose(), Op.EQ);
if (path != null) {
// for domain admin we should show only subdomains information
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<FirewallRuleVO> sc = sb.create();
if (id != null) {
sc.setParameters("id", id);
}
if (ipId != null) {
sc.setParameters("ip", ipId);
}
if (domainId != null) {
sc.setParameters("domainId", domainId);
if (accountName != null) {
Account account = _accountMgr.getActiveAccount(accountName, domainId);
sc.setParameters("accountId", account.getId());
}
}
sc.setParameters("purpose", Purpose.Firewall);
if (path != null) {
sc.setJoinParameters("domainSearch", "path", path + "%");
}
return _firewallDao.search(sc, filter);
}
@Override
public void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException {
assert newRule.getSourceIpAddressId() == ipAddress.getId() : "You passed in an ip address that doesn't match the address in the new rule";
List<FirewallRuleVO> 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.";
for (FirewallRuleVO rule : rules) {
if (rule.getId() == newRule.getId()) {
continue; // Skips my own rule.
}
if (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() != Purpose.StaticNat) {
throw new NetworkRuleConflictException("There is 1 to 1 Nat rule specified for the ip address id=" + newRule.getSourceIpAddressId());
} else if (rule.getPurpose() != Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat) {
throw new NetworkRuleConflictException("There is already firewall rule specified for the ip address id=" + newRule.getSourceIpAddressId());
}
if (rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
throw new NetworkRuleConflictException("New rule is for a different network than what's specified in rule " + rule.getXid());
}
boolean allowFirewall = ((rule.getPurpose() == Purpose.Firewall || newRule.getPurpose() == Purpose.Firewall) && newRule.getPurpose() != rule.getPurpose());
boolean notNullPorts = (newRule.getSourcePortStart() != null && newRule.getSourcePortEnd() != null && rule.getSourcePortStart() != null && rule.getSourcePortEnd() != null);
if (!allowFirewall && notNullPorts && ((rule.getSourcePortStart() <= newRule.getSourcePortStart() && rule.getSourcePortEnd() >= newRule.getSourcePortStart())
|| (rule.getSourcePortStart() <= newRule.getSourcePortEnd() && rule.getSourcePortEnd() >= newRule.getSourcePortEnd())
|| (newRule.getSourcePortStart() <= rule.getSourcePortStart() && newRule.getSourcePortEnd() >= rule.getSourcePortStart())
|| (newRule.getSourcePortStart() <= rule.getSourcePortEnd() && newRule.getSourcePortEnd() >= rule.getSourcePortEnd()))) {
// we allow port forwarding rules with the same parameters but different protocols
boolean allowPf = (rule.getPurpose() == Purpose.PortForwarding && newRule.getPurpose() == Purpose.PortForwarding && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()));
boolean allowStaticNat = (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()));
if (!(allowPf || allowStaticNat || allowFirewall)) {
throw new NetworkRuleConflictException("The range specified, " + newRule.getSourcePortStart() + "-" + newRule.getSourcePortEnd() + ", conflicts with rule " + rule.getId()
+ " which has " + rule.getSourcePortStart() + "-" + rule.getSourcePortEnd());
}
}
if (newRule.getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO) && newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())) {
if (newRule.getIcmpCode().longValue() == rule.getIcmpCode().longValue() || newRule.getIcmpType().longValue() == rule.getIcmpType().longValue() || newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())) {
throw new InvalidParameterValueException("New rule conflicts with existing rule id=" + rule.getId());
}
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("No network rule conflicts detected for " + newRule + " against " + (rules.size() - 1) + " existing rules");
}
}
@Override
public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto) {
// Validate ip address
_accountMgr.checkAccess(caller, ipAddress);
Long networkId = ipAddress.getAssociatedWithNetworkId();
if (networkId == null) {
throw new InvalidParameterValueException("Unable to create port forwarding rule ; ip id=" + ipAddress.getId() + " is not associated with any network");
}
Network network = _networkMgr.getNetwork(networkId);
assert network != null : "Can't create port forwarding rule as network associated with public ip address is null...how is it possible?";
if (portStart != null && !NetUtils.isValidPort(portStart)) {
throw new InvalidParameterValueException("publicPort is an invalid value: " + portStart);
}
if (portEnd != null && !NetUtils.isValidPort(portEnd)) {
throw new InvalidParameterValueException("Public port range is an invalid value: " + portEnd);
}
// start port can't be bigger than end port
if (portStart != null && portEnd != null && portStart > portEnd) {
throw new InvalidParameterValueException("Start port can't be bigger than end port");
}
// Verify that the network guru supports the protocol specified
Map<Network.Capability, String> firewallCapabilities = _networkMgr.getServiceCapabilities(network.getDataCenterId(), network.getNetworkOfferingId(), Service.Firewall);
String supportedProtocols = firewallCapabilities.get(Capability.SupportedProtocols).toLowerCase();
if (!supportedProtocols.contains(proto.toLowerCase())) {
throw new InvalidParameterValueException("Protocol " + proto + " is not supported in zone " + network.getDataCenterId());
}
}
@Override
public boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError) throws ResourceUnavailableException {
if (!_networkMgr.applyRules(rules, continueOnError)) {
s_logger.warn("Rules are not completely applied");
return false;
} else {
for (FirewallRule rule : rules) {
if (rule.getState() == FirewallRule.State.Revoke) {
_firewallDao.remove(rule.getId());
} else if (rule.getState() == FirewallRule.State.Add) {
FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId());
ruleVO.setState(FirewallRule.State.Active);
_firewallDao.update(ruleVO.getId(), ruleVO);
}
}
return true;
}
}
@Override
public boolean applyFirewallRules(long ipId, Account caller) throws ResourceUnavailableException {
List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurpose(ipId, Purpose.Firewall);
return applyFirewallRules(rules, false, caller);
}
@Override
public boolean applyFirewallRules(List<FirewallRuleVO> rules, boolean continueOnError, Account caller) {
if (rules.size() == 0) {
s_logger.debug("There are no firewall rules to apply for ip id=" + rules);
return true;
}
for (FirewallRuleVO rule: rules){
// load cidrs if any
rule.setSourceCidrList(_firewallCidrsDao.getSourceCidrs(rule.getId()));
}
if (caller != null) {
_accountMgr.checkAccess(caller, rules.toArray(new FirewallRuleVO[rules.size()]));
}
try {
if (!applyRules(rules, continueOnError)) {
return false;
}
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to apply firewall rules due to ", ex);
return false;
}
return true;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_FIREWALL_CLOSE, eventDescription = "revoking firewall rule", async = true)
public boolean revokeFirewallRule(long ruleId, boolean apply, Account caller, long userId) {
FirewallRuleVO rule = _firewallDao.findById(ruleId);
if (rule == null || rule.getPurpose() != Purpose.Firewall) {
throw new InvalidParameterValueException("Unable to find " + ruleId + " having purpose " + Purpose.Firewall);
}
_accountMgr.checkAccess(caller, rule);
revokeRule(rule, caller, userId, false);
boolean success = false;
if (apply) {
List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurpose(rule.getSourceIpAddressId(), Purpose.Firewall);
return applyFirewallRules(rules, false, caller);
} else {
success = true;
}
return success;
}
@Override
public boolean revokeFirewallRule(long ruleId, boolean apply) {
Account caller = UserContext.current().getCaller();
long userId = UserContext.current().getCallerUserId();
return revokeFirewallRule(ruleId, apply, caller, userId);
}
@Override
@DB
public void revokeRule(FirewallRuleVO rule, Account caller, long userId, boolean needUsageEvent) {
if (caller != null) {
_accountMgr.checkAccess(caller, rule);
}
Transaction txn = Transaction.currentTxn();
boolean generateUsageEvent = false;
txn.start();
if (rule.getState() == State.Staged) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule);
}
_firewallDao.remove(rule.getId());
generateUsageEvent = true;
} else if (rule.getState() == State.Add || rule.getState() == State.Active) {
rule.setState(State.Revoke);
_firewallDao.update(rule.getId(), rule);
generateUsageEvent = true;
}
if (generateUsageEvent && needUsageEvent) {
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_RULE_DELETE, rule.getAccountId(), 0, rule.getId(), null);
_usageEventDao.persist(usageEvent);
}
txn.commit();
}
@Override
public FirewallRule getFirewallRule(long ruleId) {
return _firewallDao.findById(ruleId);
}
@Override
public boolean revokeFirewallRulesForIp(long ipId, long userId, Account caller) throws ResourceUnavailableException {
List<FirewallRule> rules = new ArrayList<FirewallRule>();
List<FirewallRuleVO> fwRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ipId, Purpose.Firewall);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Releasing " + fwRules.size() + " firewall rules for ip id=" + ipId);
}
for (FirewallRuleVO rule : fwRules) {
// Mark all Firewall rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no need to send them one by one
revokeFirewallRule(rule.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM);
}
// now send everything to the backend
List<FirewallRuleVO> rulesToApply = _firewallDao.listByIpAndPurpose(ipId, Purpose.Firewall);
applyFirewallRules(rulesToApply, true, caller);
// Now we check again in case more rules have been inserted.
rules.addAll(_firewallDao.listByIpAndPurposeAndNotRevoked(ipId, Purpose.Firewall));
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully released firewall rules for ip id=" + ipId + " and # of rules now = " + rules.size());
}
return rules.size() == 0;
}
@Override
public FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType) throws NetworkRuleConflictException{
//If firwallRule for this port range already exists, return it
List<FirewallRuleVO> rules = _firewallDao.listByIpPurposeAndProtocolAndNotRevoked(ipAddrId, startPort, endPort, protocol, Purpose.Firewall);
if (!rules.isEmpty()) {
return rules.get(0);
}
List<String> oneCidr = new ArrayList<String>();
oneCidr.add(NetUtils.ALL_CIDRS);
return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, icmpCode, icmpType);
}
@Override
public boolean revokeAllFirewallRulesForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException {
List<FirewallRule> rules = new ArrayList<FirewallRule>();
List<FirewallRuleVO> fwRules = _firewallDao.listByNetworkAndPurposeAndNotRevoked(networkId, Purpose.Firewall);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Releasing " + fwRules.size() + " firewall rules for network id=" + networkId);
}
for (FirewallRuleVO rule : fwRules) {
// Mark all Firewall rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no need to send them one by one
revokeFirewallRule(rule.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM);
}
// now send everything to the backend
List<FirewallRuleVO> rulesToApply = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.Firewall);
applyFirewallRules(rulesToApply, true, caller);
// Now we check again in case more rules have been inserted.
rules.addAll(_firewallDao.listByNetworkAndPurposeAndNotRevoked(networkId, Purpose.Firewall));
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully released firewall rules for network id=" + networkId + " and # of rules now = " + rules.size());
}
return rules.size() == 0;
}
}

View File

@ -58,11 +58,11 @@ import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.network.rules.RulesManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@ -122,6 +122,8 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
UsageEventDao _usageEventDao;
@Inject
FirewallRulesCidrsDao _firewallCidrsDao;
@Inject
FirewallManager _firewallMgr;
@Override
@DB
@ -346,7 +348,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
@Override @DB
@ActionEvent(eventType = EventTypes.EVENT_LOAD_BALANCER_CREATE, eventDescription = "creating load balancer")
public LoadBalancer createLoadBalancerRule(LoadBalancer lb) throws NetworkRuleConflictException {
public LoadBalancer createLoadBalancerRule(LoadBalancer lb, boolean openFirewall) throws NetworkRuleConflictException {
UserContext caller = UserContext.current();
long ipId = lb.getSourceIpAddressId();
@ -362,18 +364,8 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
int defPortStart = lb.getDefaultPortStart();
int defPortEnd = lb.getDefaultPortEnd();
if (!NetUtils.isValidPort(srcPortStart)) {
throw new InvalidParameterValueException("publicPort is an invalid value: " + srcPortStart);
}
if (!NetUtils.isValidPort(srcPortEnd)) {
throw new InvalidParameterValueException("Public port range is an invalid value: " + srcPortEnd);
}
if (srcPortStart > srcPortEnd) {
throw new InvalidParameterValueException("Public port range is an invalid value: " + srcPortStart + "-" + srcPortEnd);
}
if (!NetUtils.isValidPort(defPortStart)) {
throw new InvalidParameterValueException("privatePort is an invalid value: " + defPortStart);
}
_firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol());
if (!NetUtils.isValidPort(defPortEnd)) {
throw new InvalidParameterValueException("privatePort is an invalid value: " + defPortEnd);
}
@ -384,29 +376,27 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
throw new InvalidParameterValueException("Invalid algorithm: " + lb.getAlgorithm());
}
Long networkId = ipAddr.getAssociatedWithNetworkId();
if (networkId == null) {
throw new InvalidParameterValueException("Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network");
}
_accountMgr.checkAccess(caller.getCaller(), ipAddr);
// verify that lb service is supported by the network
Network network = _networkMgr.getNetwork(networkId);
Network network = _networkMgr.getNetwork(ipAddr.getAssociatedWithNetworkId());
if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) {
throw new InvalidParameterValueException("LB service is not supported in network id=" + networkId);
throw new InvalidParameterValueException("LB service is not supported in network id=" + network.getId());
}
Transaction txn = Transaction.currentTxn();
txn.start();
if (openFirewall) {
_firewallMgr.createRuleForAllCidrs(ipId, caller.getCaller(), lb.getSourcePortStart(), lb.getSourcePortEnd(), lb.getProtocol(), null, null);
}
LoadBalancerVO newRule = new LoadBalancerVO(lb.getXid(), lb.getName(), lb.getDescription(), lb.getSourceIpAddressId(), lb.getSourcePortEnd(), lb.getDefaultPortStart(),
lb.getSourceCidrList(), lb.getAlgorithm(), networkId, ipAddr.getAccountId(), ipAddr.getDomainId());
lb.getSourceCidrList(), lb.getAlgorithm(), network.getId(), ipAddr.getAccountId(), ipAddr.getDomainId());
newRule = _lbDao.persist(newRule);
boolean success = true;
try {
_rulesMgr.detectRulesConflict(newRule, ipAddr);
_firewallMgr.detectRulesConflict(newRule, ipAddr);
if (!_rulesDao.setStateToAdd(newRule)) {
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
}
@ -415,14 +405,26 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_LOAD_BALANCER_CREATE, ipAddr.getAllocatedToAccountId(), ipAddr.getDataCenterId(), newRule.getId(), null);
_usageEventDao.persist(usageEvent);
txn.commit();
// send firewallRule to the backend
if (openFirewall) {
success = success && _firewallMgr.applyFirewallRules(lb.getSourceIpAddressId(), caller.getCaller());
}
return newRule;
} catch (Exception e) {
_lbDao.remove(newRule.getId());
success = false;
if (e instanceof NetworkRuleConflictException) {
throw (NetworkRuleConflictException) e;
}
throw new CloudRuntimeException("Unable to add rule for ip address id=" + newRule.getSourceIpAddressId(), e);
} finally {
if (!success) {
_lbDao.remove(newRule.getId());
}
}
}
@Override

View File

@ -50,10 +50,12 @@ import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetFirewallRulesCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
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.LoadBalancerTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
@ -2086,7 +2088,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
result = result && applyPortForwardingRules(router, (List<PortForwardingRule>) rules);
} else if (rules.get(0).getPurpose() == Purpose.StaticNat) {
result = result && applyStaticNatRules(router, (List<StaticNatRule>) rules);
} else {
} else if (rules.get(0).getPurpose() == Purpose.Firewall) {
result = result && applyFirewallRules(router, (List<FirewallRule>) rules);
}else {
s_logger.warn("Unable to apply rules of purpose: " + rules.get(0).getPurpose());
result = false;
}
@ -2131,4 +2135,32 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
}
return vrs;
}
private void createFirewallRulesCommands(List<? extends FirewallRule> rules, DomainRouterVO router, Commands cmds) {
List<FirewallRuleTO> rulesTO = null;
if (rules != null) {
rulesTO = new ArrayList<FirewallRuleTO>();
for (FirewallRule rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
FirewallRuleTO ruleTO = new FirewallRuleTO(rule, sourceIp.getAddress().addr());
rulesTO.add(ruleTO);
}
}
SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rulesTO);
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, router.getGuestIpAddress());
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);
}
protected boolean applyFirewallRules(DomainRouterVO router, List<FirewallRule> rules) throws ResourceUnavailableException {
Commands cmds = new Commands(OnError.Continue);
createFirewallRulesCommands(rules, router, cmds);
// Send commands to router
return sendCommandsToRouter(router, cmds);
}
}

View File

@ -0,0 +1,58 @@
package com.cloud.network.rules;
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.user.Account;
public interface FirewallManager extends FirewallService{
/**
* detectRulesConflict finds conflicts in networking rules. It checks for
* conflicts between the following types of netowrking rules;
* 1. one to one nat ip forwarding
* 2. port forwarding
* 3. load balancing
*
* It is possible for two conflicting rules to be added at the same time
* and conflicts are detected between those two rules. In this case, it
* is possible for both rules to be rolled back when, technically, we should
* only roll back one of the rules. However, the chances of that is low
* and the user can simply re-add one of the rules themselves.
*
* @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 validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto);
boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError) throws ResourceUnavailableException;
boolean applyFirewallRules(List<FirewallRuleVO> rules, boolean continueOnError, Account caller);
public void revokeRule(FirewallRuleVO rule, Account caller, long userId, boolean needUsageEvent);
boolean revokeFirewallRulesForIp(long ipId, long userId, Account caller) throws ResourceUnavailableException;
/**
* Revokes a firewall rule
* @param ruleId the id of the rule to revoke.
* @param caller TODO
* @param userId TODO
* @return
*/
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)
throws NetworkRuleConflictException;
FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType) throws NetworkRuleConflictException;
boolean revokeAllFirewallRulesForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException;
}

View File

@ -18,6 +18,7 @@
package com.cloud.network.rules;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.persistence.Column;
@ -32,6 +33,7 @@ import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.net.NetUtils;
@ -60,10 +62,10 @@ public class FirewallRuleVO implements FirewallRule {
long sourceIpAddressId;
@Column(name="start_port", updatable=false)
int sourcePortStart;
Integer sourcePortStart;
@Column(name="end_port", updatable=false)
int sourcePortEnd;
Integer sourcePortEnd;
@Column(name="protocol", updatable=false)
String protocol = NetUtils.TCP_PROTO;
@ -81,6 +83,28 @@ public class FirewallRuleVO implements FirewallRule {
@Column(name="network_id")
long networkId;
@Column(name="icmp_code")
Integer icmpCode;
@Column(name="icmp_type")
Integer icmpType;
// This is a delayed load value. If the value is null,
// then this field has not been loaded yet.
// Call firewallrules dao to load it.
@Transient
List<String> sourceCidrs;
public void setSourceCidrList(List<String> sourceCidrs) {
this.sourceCidrs=sourceCidrs;
}
@Override
public List<String> getSourceCidrList() {
return sourceCidrs;
}
@Override
public long getAccountId() {
@ -108,12 +132,12 @@ public class FirewallRuleVO implements FirewallRule {
}
@Override
public int getSourcePortStart() {
public Integer getSourcePortStart() {
return sourcePortStart;
}
@Override
public int getSourcePortEnd() {
public Integer getSourcePortEnd() {
return sourcePortEnd;
}
@ -148,7 +172,7 @@ public class FirewallRuleVO implements FirewallRule {
protected FirewallRuleVO() {
}
public FirewallRuleVO(String xId, long ipAddressId, int portStart, int portEnd, String protocol, long networkId, long accountId, long domainId, Purpose purpose) {
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) {
this.xId = xId;
if (xId == null) {
this.xId = UUID.randomUUID().toString();
@ -162,10 +186,13 @@ public class FirewallRuleVO implements FirewallRule {
this.purpose = purpose;
this.networkId = networkId;
this.state = State.Staged;
this.icmpCode = icmpCode;
this.icmpType = icmpType;
this.sourceCidrs = sourceCidrs;
}
public FirewallRuleVO(String xId, long ipAddressId, int port, String protocol, long networkId, long accountId, long domainId, Purpose purpose) {
this(xId, ipAddressId, port, port, protocol, networkId, accountId, domainId, purpose);
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) {
this(xId, ipAddressId, port, port, protocol, networkId, accountId, domainId, purpose, sourceCidrs, icmpCode, icmpType);
}
@Override
@ -173,4 +200,14 @@ public class FirewallRuleVO implements FirewallRule {
return new StringBuilder("Rule[").append(id).append("-").append(purpose).append("-").append(state).append("]").toString();
}
@Override
public Integer getIcmpCode() {
return icmpCode;
}
@Override
public Integer getIcmpType() {
return icmpType;
}
}

View File

@ -27,7 +27,6 @@ import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.cloud.utils.net.Ip;
@ -48,35 +47,17 @@ public class PortForwardingRuleVO extends FirewallRuleVO implements PortForwardi
private int destinationPortEnd;
@Column(name="instance_id")
private long virtualMachineId;
// This is a delayed load value. If the value is null,
// then this field has not been loaded yet.
// Call firewallrules dao to load it.
@Transient
List<String> sourceCidrs;
public void setSourceCidrList(List<String> sourceCidrs) {
this.sourceCidrs=sourceCidrs;
}
@Override
public List<String> getSourceCidrList() {
return sourceCidrs;
}
private long virtualMachineId;
public PortForwardingRuleVO() {
}
public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, List<String> sourceCidrs, long networkId, long accountId, long domainId, long instanceId) {
super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding);
super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding, sourceCidrs, null, null);
this.destinationIpAddress = dstIp;
this.virtualMachineId = instanceId;
this.destinationPortStart = dstPortStart;
this.destinationPortEnd = dstPortEnd;
this.sourceCidrs = sourceCidrs;
this.destinationPortEnd = dstPortEnd;
}
public PortForwardingRuleVO(String xId, long srcIpId, int srcPort, Ip dstIp, int dstPort, String protocol, List<String> sourceCidrs, long networkId, long accountId, long domainId, long instanceId) {

View File

@ -39,29 +39,10 @@ public interface RulesManager extends RulesService {
boolean applyStaticNatRulesForNetwork(long networkId, boolean continueOnError, Account caller);
/**
* detectRulesConflict finds conflicts in networking rules. It checks for
* conflicts between the following types of netowrking rules;
* 1. one to one nat ip forwarding
* 2. port forwarding
* 3. load balancing
*
* It is possible for two conflicting rules to be added at the same time
* and conflicts are detected between those two rules. In this case, it
* is possible for both rules to be rolled back when, technically, we should
* only roll back one of the rules. However, the chances of that is low
* and the user can simply re-add one of the rules themselves.
*
* @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 checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller);
void checkRuleAndUserVm(FirewallRule rule, UserVm userVm, Account caller);
boolean revokeAllRulesForIp(long ipId, long userId, Account caller) throws ResourceUnavailableException;
boolean revokeAllPFAndStaticNatRulesForIp(long ipId, long userId, Account caller) throws ResourceUnavailableException;
boolean revokeAllRulesForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException;
@ -81,7 +62,7 @@ public interface RulesManager extends RulesService {
boolean revokeStaticNatRulesForVm(long vmId);
FirewallRule[] reservePorts(IpAddress ip, String protocol, FirewallRule.Purpose purpose, int... ports) throws NetworkRuleConflictException;
FirewallRule[] reservePorts(IpAddress ip, String protocol, FirewallRule.Purpose purpose, boolean openFirewall, Account caller, int... ports) throws NetworkRuleConflictException;
boolean releasePorts(long ipId, String protocol, FirewallRule.Purpose purpose, int... ports);
List<PortForwardingRuleVO> listByNetworkId(long networkId);

View File

@ -43,14 +43,12 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
import com.cloud.network.dao.FirewallRulesCidrsDao;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRule.State;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@ -98,48 +96,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
UsageEventDao _usageEventDao;
@Inject
DomainDao _domainDao;
@Inject
FirewallManager _firewallMgr;
@Override
public void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException {
assert newRule.getSourceIpAddressId() == ipAddress.getId() : "You passed in an ip address that doesn't match the address in the new rule";
List<FirewallRuleVO> 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.";
for (FirewallRuleVO rule : rules) {
if (rule.getId() == newRule.getId()) {
continue; // Skips my own rule.
}
if (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() != Purpose.StaticNat) {
throw new NetworkRuleConflictException("There is 1 to 1 Nat rule specified for the ip address id=" + newRule.getSourceIpAddressId());
} else if (rule.getPurpose() != Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat) {
throw new NetworkRuleConflictException("There is already firewall rule specified for the ip address id=" + newRule.getSourceIpAddressId());
}
if (rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
throw new NetworkRuleConflictException("New rule is for a different network than what's specified in rule " + rule.getXid());
}
if ((rule.getSourcePortStart() <= newRule.getSourcePortStart() && rule.getSourcePortEnd() >= newRule.getSourcePortStart())
|| (rule.getSourcePortStart() <= newRule.getSourcePortEnd() && rule.getSourcePortEnd() >= newRule.getSourcePortEnd())
|| (newRule.getSourcePortStart() <= rule.getSourcePortStart() && newRule.getSourcePortEnd() >= rule.getSourcePortStart())
|| (newRule.getSourcePortStart() <= rule.getSourcePortEnd() && newRule.getSourcePortEnd() >= rule.getSourcePortEnd())) {
// we allow port forwarding rules with the same parameters but different protocols
boolean allowPf = (rule.getPurpose() == Purpose.PortForwarding && newRule.getPurpose() == Purpose.PortForwarding && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()));
boolean allowStaticNat = (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()));
if (!(allowPf || allowStaticNat)) {
throw new NetworkRuleConflictException("The range specified, " + newRule.getSourcePortStart() + "-" + newRule.getSourcePortEnd() + ", conflicts with rule " + rule.getId()
+ " which has " + rule.getSourcePortStart() + "-" + rule.getSourcePortEnd());
}
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("No network rule conflicts detected for " + newRule + " against " + (rules.size() - 1) + " existing rules");
}
}
@Override
public void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) {
@ -190,38 +150,29 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
@Override @DB
@ActionEvent(eventType = EventTypes.EVENT_NET_RULE_ADD, eventDescription = "creating forwarding rule", create = true)
public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId) throws NetworkRuleConflictException {
public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean openFirewall) throws NetworkRuleConflictException {
UserContext ctx = UserContext.current();
Account caller = ctx.getCaller();
Long networkId = null;
Long accountId = null;
Long domainId = null;
Long ipAddrId = rule.getSourceIpAddressId();
IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId);
// Validate ip address
if (ipAddress == null) {
throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " doesn't exist in the system");
} else if (ipAddress.isOneToOneNat()) {
throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " has static nat enabled");
} else {
_accountMgr.checkAccess(caller, ipAddress);
networkId = ipAddress.getAssociatedWithNetworkId();
if (networkId == null) {
throw new InvalidParameterValueException("Unable to create port forwarding rule ; ip id=" + ipAddrId + " is not associated with any network");
}
// get account/domain info from the ip address (can't get it from the network as the network can be shared between
// accounts)
accountId = ipAddress.getAccountId();
domainId = ipAddress.getDomainId();
}
}
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol());
Long networkId = ipAddress.getAssociatedWithNetworkId();
Long accountId = ipAddress.getAccountId();
Long domainId = ipAddress.getDomainId();
// start port can't be bigger than end port
if (rule.getDestinationPortStart() > rule.getDestinationPortEnd() || rule.getSourcePortStart() > rule.getSourcePortEnd()) {
if (rule.getDestinationPortStart() > rule.getDestinationPortEnd()) {
throw new InvalidParameterValueException("Start port can't be bigger than end port");
}
@ -229,17 +180,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
if ((rule.getDestinationPortEnd() - rule.getDestinationPortStart()) != (rule.getSourcePortEnd() - rule.getSourcePortStart())) {
throw new InvalidParameterValueException("Source port and destination port ranges should be of equal sizes.");
}
Network network = _networkMgr.getNetwork(networkId);
assert network != null : "Can't create port forwarding rule as network associated with public ip address is null...how is it possible?";
// Verify that the network guru supports the protocol specified
Map<Network.Capability, String> firewallCapabilities = _networkMgr.getServiceCapabilities(network.getDataCenterId(), network.getNetworkOfferingId(), Service.Firewall);
String supportedProtocols = firewallCapabilities.get(Capability.SupportedProtocols).toLowerCase();
if (!supportedProtocols.contains(rule.getProtocol().toLowerCase())) {
throw new InvalidParameterValueException("Protocol " + rule.getProtocol() + " is not supported in zone " + network.getDataCenterId());
}
// validate user VM exists
UserVm vm = _vmDao.findById(vmId);
if (vm == null) {
@ -260,12 +201,17 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
Transaction txn = Transaction.currentTxn();
txn.start();
//create firewallRule for 0.0.0.0/0 cidr
if (openFirewall) {
_firewallMgr.createRuleForAllCidrs(ipAddrId, caller, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), null, null);
}
PortForwardingRuleVO newRule = new PortForwardingRuleVO(rule.getXid(), rule.getSourceIpAddressId(), rule.getSourcePortStart(), rule.getSourcePortEnd(), dstIp, rule.getDestinationPortStart(),
rule.getDestinationPortEnd(), rule.getProtocol().toLowerCase(), rule.getSourceCidrList(), networkId, accountId, domainId, vmId);
newRule = _forwardingDao.persist(newRule);
try {
detectRulesConflict(newRule, ipAddress);
_firewallMgr.detectRulesConflict(newRule, ipAddress);
if (!_firewallDao.setStateToAdd(newRule)) {
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
}
@ -285,64 +231,45 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
@Override @DB
@ActionEvent(eventType = EventTypes.EVENT_NET_RULE_ADD, eventDescription = "creating static nat rule", create = true)
public StaticNatRule createStaticNatRule(StaticNatRule rule) throws NetworkRuleConflictException {
public StaticNatRule createStaticNatRule(StaticNatRule rule, boolean openFirewall) throws NetworkRuleConflictException {
Account caller = UserContext.current().getCaller();
Long networkId = null;
Long accountId = null;
Long domainId = null;
Long ipAddrId = rule.getSourceIpAddressId();
IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId);
// Verify ip address existst and if 1-1 nat is enabled for it
// Validate ip address
if (ipAddress == null) {
throw new InvalidParameterValueException("Unable to create static nat rule; ip id=" + ipAddrId + " doesn't exist in the system");
} else if (ipAddress.isSourceNat() || !ipAddress.isOneToOneNat() || ipAddress.getAssociatedWithVmId() == null) {
throw new NetworkRuleConflictException("Can't do static nat on ip address: " + ipAddress.getAddress());
} else {
_accountMgr.checkAccess(caller, ipAddress);
networkId = ipAddress.getAssociatedWithNetworkId();
if (networkId == null) {
throw new InvalidParameterValueException("Unable to create static nat rule ; ip id=" + ipAddrId + " is not associated with any network");
}
// get account/domain info from the ip address (can't get it from the network as the network can be shared between
// accounts)
accountId = ipAddress.getAccountId();
domainId = ipAddress.getDomainId();
}
Network network = _networkMgr.getNetwork(networkId);
assert network != null : "Can't create static nat rule as network associated with public ip address is null...how is it possible?";
}
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol());
Long networkId = ipAddress.getAssociatedWithNetworkId();
Long accountId = ipAddress.getAccountId();
Long domainId = ipAddress.getDomainId();
// Get nic IP4 address
Nic guestNic = _networkMgr.getNicInNetwork(ipAddress.getAssociatedWithVmId(), networkId);
assert (guestNic != null && guestNic.getIp4Address() != null) : "Vm doesn't belong to network associated with ipAddress or ip4 address is null...how is it possible?";
String dstIp = guestNic.getIp4Address();
// Verify that the network guru supports the protocol specified
Map<Network.Capability, String> firewallCapability = _networkMgr.getServiceCapabilities(network.getDataCenterId(), network.getNetworkOfferingId(), Service.Firewall);
String supportedProtocols = firewallCapability.get(Capability.SupportedProtocols).toLowerCase();
if (!supportedProtocols.contains(rule.getProtocol().toLowerCase())) {
throw new InvalidParameterValueException("Protocol " + rule.getProtocol() + " is not supported in zone " + network.getDataCenterId());
}
// start port can't be bigger than end port
if (rule.getSourcePortStart() > rule.getSourcePortEnd()) {
throw new InvalidParameterValueException("Start port can't be bigger than end port");
}
Transaction txn = Transaction.currentTxn();
txn.start();
//create firewallRule for 0.0.0.0/0 cidr
if (openFirewall) {
_firewallMgr.createRuleForAllCidrs(ipAddrId, caller, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), null, null);
}
FirewallRuleVO newRule = new FirewallRuleVO(rule.getXid(), rule.getSourceIpAddressId(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol().toLowerCase(),
networkId, accountId, domainId, rule.getPurpose());
networkId, accountId, domainId, rule.getPurpose(), null, null, null);
newRule = _firewallDao.persist(newRule);
try {
detectRulesConflict(newRule, ipAddress);
_firewallMgr.detectRulesConflict(newRule, ipAddress);
if (!_firewallDao.setStateToAdd(newRule)) {
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
}
@ -424,68 +351,9 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
ipAddress.setOneToOneNat(true);
ipAddress.setAssociatedWithVmId(vmId);
if ( _ipAddressDao.update(ipAddress.getId(), ipAddress))
{
List<StaticNatRule> staticNatRules = new ArrayList<StaticNatRule>();
FirewallRuleVO ruleVO = new FirewallRuleVO(null, ipAddress.getId(), 0, 0, "icmp",
networkId,vm.getAccountId(), vm.getDomainId(), Purpose.StaticNat);
staticNatRules.add(new StaticNatRuleImpl(ruleVO, guestNic.getIp4Address()));
try {
if (!applyRules(staticNatRules, true)) {
return false;
}
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to apply icmp firewall rules due to ", ex);
return false;
}
return true;
}
return false;
return _ipAddressDao.update(ipAddress.getId(), ipAddress);
}
@DB
protected void revokeRule(FirewallRuleVO rule, Account caller, long userId) {
if (caller != null) {
_accountMgr.checkAccess(caller, rule);
}
Transaction txn = Transaction.currentTxn();
boolean generateUsageEvent = false;
txn.start();
if (rule.getState() == State.Staged) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule);
}
_firewallDao.remove(rule.getId());
generateUsageEvent = true;
} else if (rule.getState() == State.Add || rule.getState() == State.Active) {
rule.setState(State.Revoke);
_firewallDao.update(rule.getId(), rule);
generateUsageEvent = true;
}
if (generateUsageEvent) {
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_RULE_DELETE, rule.getAccountId(), 0, rule.getId(), null);
_usageEventDao.persist(usageEvent);
}
// Save and create the event
String ruleName = rule.getPurpose() == Purpose.Firewall ? "Firewall" : (rule.getPurpose() == FirewallRule.Purpose.StaticNat ? "ip forwarding" : "port forwarding");
StringBuilder description = new StringBuilder("deleted ").append(ruleName).append(" rule [ipAddressId=").append(rule.getSourceIpAddressId()).append(":").append(rule.getSourcePortStart())
.append("-").append(rule.getSourcePortEnd()).append("]");
if (rule.getPurpose() == Purpose.PortForwarding) {
PortForwardingRuleVO pfRule = (PortForwardingRuleVO) rule;
description.append("->[").append(pfRule.getDestinationIpAddress()).append(":").append(pfRule.getDestinationPortStart()).append("-").append(pfRule.getDestinationPortEnd()).append("]");
}
description.append(" ").append(rule.getProtocol());
txn.commit();
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_NET_RULE_DELETE, eventDescription = "revoking forwarding rule", async = true)
@ -506,7 +374,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
private boolean revokePortForwardingRuleInternal(long ruleId, Account caller, long userId, boolean apply) {
PortForwardingRuleVO rule = _forwardingDao.findById(ruleId);
revokeRule(rule, caller, userId);
_firewallMgr.revokeRule(rule, caller, userId, true);
boolean success = false;
@ -538,7 +406,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
private boolean revokeStaticNatRuleInternal(long ruleId, Account caller, long userId, boolean apply) {
FirewallRuleVO rule = _firewallDao.findById(ruleId);
revokeRule(rule, caller, userId);
_firewallMgr.revokeRule(rule, caller, userId, true);
boolean success = false;
@ -716,7 +584,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
try {
if (!applyRules(rules, continueOnError)) {
if (!_firewallMgr.applyRules(rules, continueOnError)) {
return false;
}
} catch (ResourceUnavailableException ex) {
@ -764,7 +632,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
try {
if (!applyRules(staticNatRules, continueOnError)) {
if (!_firewallMgr.applyRules(staticNatRules, continueOnError)) {
return false;
}
} catch (ResourceUnavailableException ex) {
@ -788,7 +656,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
try {
if (!applyRules(rules, continueOnError)) {
if (!_firewallMgr.applyRules(rules, continueOnError)) {
return false;
}
} catch (ResourceUnavailableException ex) {
@ -818,7 +686,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
try {
if (!applyRules(staticNatRules, continueOnError)) {
if (!_firewallMgr.applyRules(staticNatRules, continueOnError)) {
return false;
}
} catch (ResourceUnavailableException ex) {
@ -829,24 +697,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return true;
}
private boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError) throws ResourceUnavailableException {
if (!_networkMgr.applyRules(rules, continueOnError)) {
s_logger.warn("Rules are not completely applied");
return false;
} else {
for (FirewallRule rule : rules) {
if (rule.getState() == FirewallRule.State.Revoke) {
_firewallDao.remove(rule.getId());
} else if (rule.getState() == FirewallRule.State.Add) {
FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId());
ruleVO.setState(FirewallRule.State.Active);
_firewallDao.update(ruleVO.getId(), ruleVO);
}
}
return true;
}
}
@Override
public List<? extends FirewallRule> searchStaticNatRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId) {
Account caller = UserContext.current().getCaller();
@ -934,7 +784,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
public boolean revokeAllRulesForIp(long ipId, long userId, Account caller) throws ResourceUnavailableException {
public boolean revokeAllPFAndStaticNatRulesForIp(long ipId, long userId, Account caller) throws ResourceUnavailableException {
List<FirewallRule> rules = new ArrayList<FirewallRule>();
List<PortForwardingRuleVO> pfRules = _forwardingDao.listByIpAndNotRevoked(ipId);
@ -1048,13 +898,18 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
@Override
@DB
public FirewallRuleVO[] reservePorts(IpAddress ip, String protocol, FirewallRule.Purpose purpose, int... ports) throws NetworkRuleConflictException {
public FirewallRuleVO[] reservePorts(IpAddress ip, String protocol, FirewallRule.Purpose purpose, boolean openFirewall, Account caller, int... ports) throws NetworkRuleConflictException {
FirewallRuleVO[] rules = new FirewallRuleVO[ports.length];
Transaction txn = Transaction.currentTxn();
txn.start();
for (int i = 0; i < ports.length; i++) {
rules[i] = new FirewallRuleVO(null, ip.getId(), ports[i], protocol, ip.getAssociatedWithNetworkId(), ip.getAllocatedToAccountId(), ip.getAllocatedInDomainId(), purpose);
if (openFirewall) {
_firewallMgr.createRuleForAllCidrs(ip.getId(), caller, ports[i], ports[i], protocol, null, null);
}
rules[i] = new FirewallRuleVO(null, ip.getId(), ports[i], protocol, ip.getAssociatedWithNetworkId(), ip.getAllocatedToAccountId(), ip.getAllocatedInDomainId(), purpose, null, null, null);
rules[i] = _firewallDao.persist(rules[i]);
}
txn.commit();
@ -1062,7 +917,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
boolean success = false;
try {
for (FirewallRuleVO newRule : rules) {
detectRulesConflict(newRule, ip);
_firewallMgr.detectRulesConflict(newRule, ip);
}
success = true;
return rules;
@ -1117,33 +972,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new InvalidParameterValueException("One to one nat is not enabled for the ip id=" + ipId);
}
if (!revokeAllRulesForIp(ipId, UserContext.current().getCallerUserId(), caller)) {
if (!revokeAllPFAndStaticNatRulesForIp(ipId, UserContext.current().getCallerUserId(), caller)) {
s_logger.warn("Unable to revoke all static nat rules for ip " + ipAddress);
success = false;
}
if (success)
{
long vmId = ipAddress.getAssociatedWithVmId();
Nic guestNic = _networkMgr.getNicInNetwork(vmId, ipAddress.getAssociatedWithNetworkId());
if (guestNic == null) {
throw new InvalidParameterValueException("Vm doesn't belong to the network " + ipAddress.getAssociatedWithNetworkId());
}
List<StaticNatRule> staticNatRules = new ArrayList<StaticNatRule>();
FirewallRuleVO ruleVO = new FirewallRuleVO(null, ipAddress.getId(), 0, 0, "icmp",
ipAddress.getAssociatedWithNetworkId(),ipAddress.getAccountId(), ipAddress.getDomainId(), Purpose.StaticNat);
ruleVO.setState(State.Revoke);
staticNatRules.add(new StaticNatRuleImpl(ruleVO, guestNic.getIp4Address()));
try {
if (!applyRules(staticNatRules, true)) {
return false;
}
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to apply icmp firewall rules due to ", ex);
return false;
}
}
if (success) {
ipAddress.setOneToOneNat(false);
ipAddress.setAssociatedWithVmId(null);
@ -1178,5 +1010,5 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return new StaticNatRuleImpl(ruleVO, guestNic.getIp4Address());
}
}

View File

@ -18,6 +18,8 @@
package com.cloud.network.rules;
import java.util.List;
public class StaticNatRuleImpl implements StaticNatRule{
long id;
@ -52,7 +54,7 @@ public class StaticNatRuleImpl implements StaticNatRule{
}
@Override
public int getSourcePortEnd() {
public Integer getSourcePortEnd() {
return portEnd;
}
@ -87,7 +89,7 @@ public class StaticNatRuleImpl implements StaticNatRule{
}
@Override
public int getSourcePortStart() {
public Integer getSourcePortStart() {
return portStart;
}
@ -105,4 +107,19 @@ public class StaticNatRuleImpl implements StaticNatRule{
public String getXid() {
return xid;
}
@Override
public Integer getIcmpCode() {
return null;
}
@Override
public Integer getIcmpType() {
return null;
}
@Override
public List<String> getSourceCidrList() {
return null;
}
}

View File

@ -24,17 +24,13 @@ import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.network.dao.FirewallRulesCidrsDaoImpl;
import com.cloud.network.dao.FirewallRulesDaoImpl;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRule.State;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.SearchCriteria.Op;
@Local(value=PortForwardingRulesDao.class)
@ -153,50 +149,5 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase<PortForwardingRul
return listBy(sc);
}
public void saveSourceCidrs(PortForwardingRuleVO portForwardingRule) {
List<String> cidrlist = portForwardingRule.getSourceCidrList();
if (cidrlist == null) {
return;
}
_portForwardingRulesCidrsDao.persist(portForwardingRule.getId(), cidrlist);
}
public void loadSourceCidrs(PortForwardingRuleVO portForwardingRule){
List<String> sourceCidrs = _portForwardingRulesCidrsDao.getSourceCidrs(portForwardingRule.getId());
portForwardingRule.setSourceCidrList(sourceCidrs);
}
@Override @DB
public PortForwardingRuleVO persist(PortForwardingRuleVO portForwardingRule) {
Transaction txn = Transaction.currentTxn();
txn.start();
PortForwardingRuleVO dbfirewallRule = super.persist(portForwardingRule);
saveSourceCidrs(portForwardingRule);
txn.commit();
return dbfirewallRule;
}
@Override @DB
public boolean update(Long portForwardingRuleId, PortForwardingRuleVO portForwardingRule) {
Transaction txn = Transaction.currentTxn();
txn.start();
boolean persisted = super.update(portForwardingRuleId, portForwardingRule);
if (!persisted) {
return persisted;
}
saveSourceCidrs(portForwardingRule);
txn.commit();
return persisted;
}
}

View File

@ -50,6 +50,7 @@ import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.RulesManager;
@ -87,6 +88,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
@Inject RulesManager _rulesMgr;
@Inject DomainDao _domainDao;
@Inject FirewallRulesDao _rulesDao;
@Inject FirewallManager _firewallMgr;
int _userLimit;
int _pskLength;
@ -94,7 +96,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
SearchBuilder<RemoteAccessVpnVO> VpnSearch;
@Override
public RemoteAccessVpn createRemoteAccessVpn(long publicIpId, String ipRange) throws NetworkRuleConflictException {
public RemoteAccessVpn createRemoteAccessVpn(long publicIpId, String ipRange, boolean openFirewall) throws NetworkRuleConflictException {
UserContext ctx = UserContext.current();
Account caller = ctx.getCaller();
@ -165,7 +167,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
long startIp = NetUtils.ip2Long(range[0]);
String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1];
String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength);
_rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT);
_rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewall, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT);
vpnVO = new RemoteAccessVpnVO(ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId(), ipAddr.getAssociatedWithNetworkId(),
publicIpId, range[0], newIpRange, sharedSecret);
return _remoteAccessVpnDao.persist(vpnVO);
@ -302,7 +304,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
}
@Override
public RemoteAccessVpnVO startRemoteAccessVpn(long vpnId) throws ResourceUnavailableException {
public RemoteAccessVpnVO startRemoteAccessVpn(long vpnId, boolean openFirewall) throws ResourceUnavailableException {
Account caller = UserContext.current().getCaller();
RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findById(vpnId);
@ -311,18 +313,28 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
}
_accountMgr.checkAccess(caller, vpn);
Network network = _networkMgr.getNetwork(vpn.getNetworkId());
List<? extends RemoteAccessVpnElement> elements = _networkMgr.getRemoteAccessVpnElements();
boolean started = false;
try {
for (RemoteAccessVpnElement element : elements) {
if (element.startVpn(network, vpn)) {
started = true;
break;
boolean firewallOpened = true;
if (openFirewall) {
firewallOpened = _firewallMgr.applyFirewallRules(vpn.getServerAddressId(), caller);
}
if (firewallOpened) {
for (RemoteAccessVpnElement element : elements) {
if (element.startVpn(network, vpn)) {
started = true;
break;
}
}
}
return vpn;
} finally {
if (started) {

View File

@ -333,7 +333,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
String publicCidr = NetUtils.ipAndNetMaskToCidr(secStorageVm.getPublicIpAddress(), secStorageVm.getPublicNetmask());
if (NetUtils.isNetworkAWithinNetworkB(privateCidr, publicCidr) || NetUtils.isNetworkAWithinNetworkB(publicCidr, privateCidr)) {
s_logger.info("private and public interface overlaps, add a default route through private interface. privateCidr: " + privateCidr + ", publicCidr: " + publicCidr);
allowedCidrs.add("0.0.0.0/0");
allowedCidrs.add(NetUtils.ALL_CIDRS);
}
setupCmd.setAllowedInternalSites(allowedCidrs.toArray(new String[allowedCidrs.size()]));
}

View File

@ -578,8 +578,8 @@ CREATE TABLE `cloud`.`op_dc_vnet_alloc` (
CREATE TABLE `cloud`.`firewall_rules` (
`id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
`ip_address_id` bigint unsigned NOT NULL COMMENT 'id of the corresponding ip address',
`start_port` int(10) NOT NULL COMMENT 'starting port of a port range',
`end_port` int(10) NOT NULL COMMENT 'end port of a port range',
`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',
`protocol` char(16) NOT NULL default 'TCP' COMMENT 'protocol to open these ports for',
`purpose` char(32) NOT NULL COMMENT 'why are these ports opened?',
@ -588,6 +588,8 @@ CREATE TABLE `cloud`.`firewall_rules` (
`network_id` bigint unsigned NOT NULL COMMENT 'network id',
`xid` char(40) NOT NULL COMMENT 'external id',
`created` datetime COMMENT 'Date created',
`icmp_code` int(10) COMMENT 'The ICMP code (if protocol=ICMP). A value of -1 means all codes for the given ICMP type.',
`icmp_type` int(10) COMMENT 'The ICMP type (if protocol=ICMP). A value of -1 means all types.',
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,

View File

@ -54,6 +54,8 @@ public class NetUtils {
public final static String ANY_PROTO = "any";
public final static String ICMP_PROTO = "icmp";
public final static String ALL_PROTO = "all";
public final static String ALL_CIDRS = "0.0.0.0/0";
private final static Random _rand = new Random(System.currentTimeMillis());