mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-9669:Advaced zone isolated network egress destination cidr support
CLOUDSTACK-9669:egress destination cidr VR python script changes
CLOUDSTACK-9669:egress destination API and orchestration changes
CLOUDSTACK-9669: Added the ipset package in systemvm template
CLOUDSTACK-9669:Added licence header for new files
CLOUDSTACK-9669: replacing 0.0.0.0/0 with the network cidr
ipset member add with 0.0.0.0/0 fails. So 0.0.0.0/0 replaced with the network cidr.
In source cidr 0.0.0.0/0 is nothing but network cidr.
updated the default egress all cidr with network cidr
This commit is contained in:
parent
278514f623
commit
065fa1c849
@ -48,6 +48,7 @@ public class FirewallRuleTO implements InternalIdentity {
|
||||
boolean revoked;
|
||||
boolean alreadyAdded;
|
||||
private List<String> sourceCidrList;
|
||||
private List<String> destCidrList;
|
||||
FirewallRule.Purpose purpose;
|
||||
private Integer icmpType;
|
||||
private Integer icmpCode;
|
||||
@ -170,6 +171,7 @@ public class FirewallRuleTO implements InternalIdentity {
|
||||
rule.getSourceCidrList(),
|
||||
rule.getIcmpType(),
|
||||
rule.getIcmpCode());
|
||||
this.destCidrList = rule.getDestinationCidrList();
|
||||
this.trafficType = trafficType;
|
||||
this.defaultEgressPolicy = defaultEgressPolicy;
|
||||
}
|
||||
@ -257,6 +259,10 @@ public class FirewallRuleTO implements InternalIdentity {
|
||||
return sourceCidrList;
|
||||
}
|
||||
|
||||
public List<String> getDestCidrList(){
|
||||
return destCidrList;
|
||||
}
|
||||
|
||||
public boolean isAlreadyAdded() {
|
||||
return alreadyAdded;
|
||||
}
|
||||
|
||||
@ -79,6 +79,8 @@ public interface FirewallRule extends ControlledEntity, Identity, InternalIdenti
|
||||
|
||||
List<String> getSourceCidrList();
|
||||
|
||||
List<String> getDestinationCidrList();
|
||||
|
||||
Long getRelated();
|
||||
|
||||
FirewallRuleType getType();
|
||||
|
||||
@ -48,6 +48,7 @@ public class ApiConstants {
|
||||
public static final String CIDR = "cidr";
|
||||
public static final String IP6_CIDR = "ip6cidr";
|
||||
public static final String CIDR_LIST = "cidrlist";
|
||||
public static final String DEST_CIDR_LIST = "destcidrlist";
|
||||
public static final String CLEANUP = "cleanup";
|
||||
public static final String MAKEREDUNDANTE = "makeredundant";
|
||||
public static final String CLUSTER_ID = "clusterid";
|
||||
|
||||
@ -77,6 +77,9 @@ public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements F
|
||||
@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.DEST_CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic to")
|
||||
private List<String> destCidrList;
|
||||
|
||||
@Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent")
|
||||
private Integer icmpType;
|
||||
|
||||
@ -113,6 +116,11 @@ public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements F
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDestinationCidrList(){
|
||||
return destCidrList;
|
||||
}
|
||||
|
||||
public Long getVpcId() {
|
||||
Network network = _networkService.getNetwork(getNetworkId());
|
||||
if (network == null) {
|
||||
@ -136,6 +144,10 @@ public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements F
|
||||
cidrlist = cidrs;
|
||||
}
|
||||
|
||||
public void setDestCidrList(List<String> cidrs){
|
||||
destCidrList = cidrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException {
|
||||
CallContext callerContext = CallContext.current();
|
||||
@ -245,6 +257,16 @@ public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements F
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destination CIDR formatting check. Since it's optional param, no need to set a default as in the case of source.
|
||||
if(destCidrList != null){
|
||||
for(String cidr : destCidrList){
|
||||
if(!NetUtils.isValidCIDR(cidr)) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Destination cidrs formatting error" + cidr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getProtocol().equalsIgnoreCase(NetUtils.ALL_PROTO)) {
|
||||
if (getSourcePortStart() != null && getSourcePortEnd() != null) {
|
||||
throw new InvalidParameterValueException("Do not pass ports to protocol ALL, protocol ALL do not require ports. Unable to create " +
|
||||
|
||||
@ -349,6 +349,11 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDestinationCidrList(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
return FirewallRule.class;
|
||||
|
||||
@ -429,6 +429,11 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDestinationCidrList(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
if (display != null) {
|
||||
|
||||
@ -323,6 +323,11 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDestinationCidrList(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
return FirewallRule.class;
|
||||
|
||||
@ -79,6 +79,10 @@ public class FirewallResponse extends BaseResponse {
|
||||
@Param(description = "is rule for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
|
||||
private Boolean forDisplay;
|
||||
|
||||
@SerializedName(ApiConstants.DEST_CIDR_LIST)
|
||||
@Param(description = "the cidr list to forward traffic to")
|
||||
private String destCidr;
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
@ -130,4 +134,8 @@ public class FirewallResponse extends BaseResponse {
|
||||
public void setForDisplay(Boolean forDisplay) {
|
||||
this.forDisplay = forDisplay;
|
||||
}
|
||||
|
||||
public void setDestCidr(String cidrList){
|
||||
this.destCidr = cidrList;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,13 +56,13 @@ public class SetFirewallRulesCommand extends NetworkElementCommand {
|
||||
if (fwTO.revoked()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
/* This entry is added just to make sure atleast there will one entry in the list to get the ipaddress */
|
||||
sb.append(fwTO.getSrcIp()).append(":reverted:0:0:0:");
|
||||
sb.append(fwTO.getSrcIp()).append(":reverted:0:0:0:0:").append(fwTO.getId()).append(":");
|
||||
String fwRuleEntry = sb.toString();
|
||||
toAdd.add(fwRuleEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> cidr;
|
||||
List<String> sCidr, dCidr;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(fwTO.getSrcIp()).append(":").append(fwTO.getProtocol()).append(":");
|
||||
if ("icmp".compareTo(fwTO.getProtocol()) == 0) {
|
||||
@ -73,12 +73,13 @@ public class SetFirewallRulesCommand extends NetworkElementCommand {
|
||||
else
|
||||
sb.append(fwTO.getStringSrcPortRange()).append(":");
|
||||
|
||||
cidr = fwTO.getSourceCidrList();
|
||||
if (cidr == null || cidr.isEmpty()) {
|
||||
sb.append("0.0.0.0/0");
|
||||
sCidr = fwTO.getSourceCidrList();
|
||||
dCidr = fwTO.getDestCidrList();
|
||||
if (sCidr == null || sCidr.isEmpty()) {
|
||||
sb.append("0.0.0.0/0"); //check if this is necessary because we are providing the source cidr by default???
|
||||
} else {
|
||||
boolean firstEntry = true;
|
||||
for (String tag : cidr) {
|
||||
for (String tag : sCidr) {
|
||||
if (!firstEntry)
|
||||
sb.append("-");
|
||||
sb.append(tag);
|
||||
@ -86,8 +87,23 @@ public class SetFirewallRulesCommand extends NetworkElementCommand {
|
||||
}
|
||||
}
|
||||
sb.append(":");
|
||||
String fwRuleEntry = sb.toString();
|
||||
|
||||
if(dCidr == null || dCidr.isEmpty()){
|
||||
sb.append("");
|
||||
}
|
||||
else{
|
||||
boolean firstEntry = true;
|
||||
for(String cidr : dCidr){
|
||||
if(!firstEntry)
|
||||
sb.append("-");
|
||||
sb.append(cidr);
|
||||
firstEntry = false;
|
||||
}
|
||||
}
|
||||
sb.append(":");
|
||||
sb.append(fwTO.getId());
|
||||
sb.append(":");
|
||||
String fwRuleEntry = sb.toString();
|
||||
toAdd.add(fwRuleEntry);
|
||||
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public class SetFirewallRulesConfigItem extends AbstractConfigItemFacade{
|
||||
final List<FirewallRule> rules = new ArrayList<FirewallRule>();
|
||||
for (final FirewallRuleTO rule : command.getRules()) {
|
||||
final FirewallRule fwRule = new FirewallRule(rule.getId(), rule.getSrcVlanTag(), rule.getSrcIp(), rule.getProtocol(), rule.getSrcPortRange(), rule.revoked(),
|
||||
rule.isAlreadyAdded(), rule.getSourceCidrList(), rule.getPurpose().toString(), rule.getIcmpType(), rule.getIcmpCode(), rule.getTrafficType().toString(),
|
||||
rule.isAlreadyAdded(), rule.getSourceCidrList(), rule.getDestCidrList(), rule.getPurpose().toString(), rule.getIcmpType(), rule.getIcmpCode(), rule.getTrafficType().toString(),
|
||||
rule.getGuestCidr(), rule.isDefaultEgressPolicy());
|
||||
rules.add(fwRule);
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ public class FirewallRule {
|
||||
private boolean revoked;
|
||||
private boolean alreadyAdded;
|
||||
private List<String> sourceCidrList;
|
||||
private List<String> destCidrList;
|
||||
private String purpose;
|
||||
private Integer icmpType;
|
||||
private Integer icmpCode;
|
||||
@ -43,7 +44,7 @@ public class FirewallRule {
|
||||
}
|
||||
|
||||
public FirewallRule(long id, String srcVlanTag, String srcIp, String protocol, int[] srcPortRange, boolean revoked, boolean alreadyAdded, List<String> sourceCidrList,
|
||||
String purpose, Integer icmpType, Integer icmpCode, String trafficType, String guestCidr, boolean defaultEgressPolicy) {
|
||||
List<String> destCidrList, String purpose, Integer icmpType, Integer icmpCode, String trafficType, String guestCidr, boolean defaultEgressPolicy) {
|
||||
this.id = id;
|
||||
this.srcVlanTag = srcVlanTag;
|
||||
this.srcIp = srcIp;
|
||||
@ -58,6 +59,7 @@ public class FirewallRule {
|
||||
this.trafficType = trafficType;
|
||||
this.guestCidr = guestCidr;
|
||||
this.defaultEgressPolicy = defaultEgressPolicy;
|
||||
this.destCidrList = destCidrList;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
|
||||
@ -149,6 +149,11 @@ public class StaticNatRuleImpl implements StaticNatRule {
|
||||
return forDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDestinationCidrList(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
return FirewallRule.class;
|
||||
|
||||
@ -449,6 +449,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
|
||||
|
||||
final Command[] cmds = checkForCommandsAndTag(commands);
|
||||
|
||||
//check what agent is returned.
|
||||
final AgentAttache agent = getAttache(hostId);
|
||||
if (agent == null || agent.isClosed()) {
|
||||
throw new AgentUnavailableException("agent not logged into this management server", hostId);
|
||||
|
||||
@ -158,8 +158,9 @@
|
||||
<bean id="externalFirewallDeviceDaoImpl" class="com.cloud.network.dao.ExternalFirewallDeviceDaoImpl" />
|
||||
<bean id="externalLoadBalancerDeviceDaoImpl" class="com.cloud.network.dao.ExternalLoadBalancerDeviceDaoImpl" />
|
||||
<bean id="externalPublicIpStatisticsDaoImpl" class="com.cloud.usage.dao.ExternalPublicIpStatisticsDaoImpl" />
|
||||
<bean id="firewallRulesCidrsDaoImpl" class="com.cloud.network.dao.FirewallRulesCidrsDaoImpl" />
|
||||
<bean id="firewallRulesDaoImpl" class="com.cloud.network.dao.FirewallRulesDaoImpl" />
|
||||
<bean id="firewallRulesCidrsDaoImpl" class="com.cloud.network.dao.FirewallRulesCidrsDaoImpl" />
|
||||
<bean id="firewallRulesDcidrsDaoImpl" class="com.cloud.network.dao.FirewallRulesDcidrsDaoImpl" />
|
||||
<bean id="MonitoringServiceDaoImpl" class="com.cloud.network.dao.MonitoringServiceDaoImpl" />
|
||||
<bean id="OpRouterMonitorServiceDaoImpl" class="com.cloud.network.dao.OpRouterMonitorServiceDaoImpl" />
|
||||
<bean id="globalLoadBalancerDaoImpl" class="org.apache.cloudstack.region.gslb.GlobalLoadBalancerDaoImpl" />
|
||||
|
||||
@ -71,8 +71,8 @@ public class FirewallRulesCidrsDaoImpl extends GenericDaoBase<FirewallRulesCidrs
|
||||
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||
|
||||
txn.start();
|
||||
for (String tag : sourceCidrs) {
|
||||
FirewallRulesCidrsVO vo = new FirewallRulesCidrsVO(firewallRuleId, tag);
|
||||
for (String cidr : sourceCidrs) {
|
||||
FirewallRulesCidrsVO vo = new FirewallRulesCidrsVO(firewallRuleId, cidr);
|
||||
persist(vo);
|
||||
}
|
||||
txn.commit();
|
||||
|
||||
@ -64,4 +64,6 @@ public interface FirewallRulesDao extends GenericDao<FirewallRuleVO, Long> {
|
||||
List<FirewallRuleVO> listByIpAndPurposeWithState(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state);
|
||||
|
||||
void loadSourceCidrs(FirewallRuleVO rule);
|
||||
|
||||
void loadDestinationCidrs(FirewallRuleVO rule);
|
||||
}
|
||||
|
||||
@ -54,6 +54,8 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
|
||||
@Inject
|
||||
protected FirewallRulesCidrsDao _firewallRulesCidrsDao;
|
||||
@Inject
|
||||
protected FirewallRulesDcidrsDao _firewallRulesDcidrsDao;
|
||||
@Inject
|
||||
ResourceTagDao _tagsDao;
|
||||
@Inject
|
||||
IPAddressDao _ipDao;
|
||||
@ -224,8 +226,17 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
|
||||
txn.start();
|
||||
|
||||
FirewallRuleVO dbfirewallRule = super.persist(firewallRule);
|
||||
|
||||
//Fill the firewall_rules_cidrs table
|
||||
saveSourceCidrs(firewallRule, firewallRule.getSourceCidrList());
|
||||
|
||||
//Fill the firewall_ruls_dcidrs table
|
||||
saveDestinationCidrs(firewallRule, firewallRule.getDestinationCidrList());
|
||||
|
||||
//Add the source and dest cidrs into the dbfirewall rule to be returned.
|
||||
//Have to read again from DB as the fields are transient.
|
||||
loadSourceCidrs(dbfirewallRule);
|
||||
loadDestinationCidrs(dbfirewallRule);
|
||||
|
||||
txn.commit();
|
||||
return dbfirewallRule;
|
||||
@ -238,6 +249,14 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
|
||||
_firewallRulesCidrsDao.persist(firewallRule.getId(), cidrList);
|
||||
}
|
||||
|
||||
public void saveDestinationCidrs(FirewallRuleVO firewallRule, List<String> cidrList){
|
||||
if(cidrList == null){
|
||||
return;
|
||||
}
|
||||
_firewallRulesDcidrsDao.persist(firewallRule.getId(), cidrList);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FirewallRuleVO> listByIpPurposeAndProtocolAndNotRevoked(long ipAddressId, Integer startPort, Integer endPort, String protocol,
|
||||
FirewallRule.Purpose purpose) {
|
||||
@ -360,4 +379,11 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
|
||||
List<String> sourceCidrs = _firewallRulesCidrsDao.getSourceCidrs(rule.getId());
|
||||
rule.setSourceCidrList(sourceCidrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDestinationCidrs(FirewallRuleVO rule){
|
||||
List<String> destCidrs = _firewallRulesDcidrsDao.getDestCidrs(rule.getId());
|
||||
rule.setDestinationCidrsList(destCidrs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.network.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface FirewallRulesDcidrsDao extends GenericDao<FirewallRulesDestCidrsVO, Long> {
|
||||
|
||||
void persist(long firewallRuleId, List<String> destCidrs);
|
||||
|
||||
List<String> getDestCidrs(long firewallId);
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.network.dao;
|
||||
|
||||
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.TransactionCallbackNoReturn;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Local(value = FirewallRulesDcidrsDao.class)
|
||||
public class FirewallRulesDcidrsDaoImpl extends GenericDaoBase<FirewallRulesDestCidrsVO, Long> implements FirewallRulesDcidrsDao {
|
||||
|
||||
protected final SearchBuilder<FirewallRulesDestCidrsVO> cidrsSearch;
|
||||
|
||||
protected FirewallRulesDcidrsDaoImpl(){
|
||||
cidrsSearch = createSearchBuilder();
|
||||
cidrsSearch.and("firewallRuleId", cidrsSearch.entity().getFirewallRuleId(), SearchCriteria.Op.EQ);
|
||||
cidrsSearch.done();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public List<String> getDestCidrs(long firewallRuleId){
|
||||
SearchCriteria<FirewallRulesDestCidrsVO> sc =cidrsSearch.create();
|
||||
sc.setParameters("firewallRuleId", firewallRuleId);
|
||||
|
||||
List<FirewallRulesDestCidrsVO> results = search(sc, null);
|
||||
|
||||
List<String> cidrs = new ArrayList<String>(results.size());
|
||||
for (FirewallRulesDestCidrsVO result : results) {
|
||||
cidrs.add(result.getCidr());
|
||||
}
|
||||
|
||||
return cidrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public void persist(final long firewallRuleId, final List<String> destCidrs){
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
for(String cidr: destCidrs){
|
||||
FirewallRulesDestCidrsVO vo = new FirewallRulesDestCidrsVO(firewallRuleId, cidr);
|
||||
persist(vo);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.network.dao;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = ("firewall_rules_dcidrs"))
|
||||
public class FirewallRulesDestCidrsVO implements InternalIdentity{
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "firewall_rule_id")
|
||||
private long firewallRuleId;
|
||||
|
||||
@Column(name = "destination_cidr")
|
||||
private String destCidr;
|
||||
|
||||
public FirewallRulesDestCidrsVO(){
|
||||
|
||||
}
|
||||
|
||||
public FirewallRulesDestCidrsVO(long firewallRuleId, String destCidr){
|
||||
this.firewallRuleId = firewallRuleId;
|
||||
this.destCidr = destCidr;
|
||||
}
|
||||
|
||||
public long getFirewallRuleId(){
|
||||
return firewallRuleId;
|
||||
}
|
||||
|
||||
public String getCidr(){
|
||||
return destCidr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@ -110,6 +110,9 @@ public class FirewallRuleVO implements FirewallRule {
|
||||
@Transient
|
||||
List<String> sourceCidrs;
|
||||
|
||||
@Transient
|
||||
List<String> destinationCidrs;
|
||||
|
||||
@Column(name = "uuid")
|
||||
String uuid;
|
||||
|
||||
@ -117,6 +120,15 @@ public class FirewallRuleVO implements FirewallRule {
|
||||
this.sourceCidrs = sourceCidrs;
|
||||
}
|
||||
|
||||
public void setDestinationCidrsList(List<String> destinationCidrs){
|
||||
this.destinationCidrs = destinationCidrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDestinationCidrList(){
|
||||
return destinationCidrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSourceCidrList() {
|
||||
return sourceCidrs;
|
||||
@ -213,6 +225,9 @@ public class FirewallRuleVO implements FirewallRule {
|
||||
this.icmpType = icmpType;
|
||||
this.sourceCidrs = sourceCidrs;
|
||||
|
||||
this.destinationCidrs = null;
|
||||
|
||||
|
||||
if (related != null) {
|
||||
assert (purpose == Purpose.Firewall) : "related field can be set for rule of purpose " + Purpose.Firewall + " only";
|
||||
}
|
||||
@ -224,7 +239,7 @@ public class FirewallRuleVO implements FirewallRule {
|
||||
}
|
||||
|
||||
public FirewallRuleVO(String xId, Long ipAddressId, Integer portStart, Integer portEnd, String protocol, long networkId, long accountId, long domainId,
|
||||
Purpose purpose, List<String> sourceCidrs, Integer icmpCode, Integer icmpType, Long related, TrafficType trafficType, FirewallRuleType type) {
|
||||
Purpose purpose, List<String> sourceCidrs, List<String> destinationCidrs, Integer icmpCode, Integer icmpType, Long related, TrafficType trafficType, FirewallRuleType type) {
|
||||
this(xId, ipAddressId, portStart, portEnd, protocol, networkId, accountId, domainId, purpose, sourceCidrs, icmpCode, icmpType, related, trafficType);
|
||||
this.type = type;
|
||||
}
|
||||
@ -234,6 +249,13 @@ public class FirewallRuleVO implements FirewallRule {
|
||||
this(xId, ipAddressId, port, port, protocol, networkId, accountId, domainId, purpose, sourceCidrs, icmpCode, icmpType, related, null);
|
||||
}
|
||||
|
||||
|
||||
public FirewallRuleVO(String xId, Long ipAddressId, Integer portStart, Integer portEnd, String protocol, long networkId, long accountId, long domainId,
|
||||
Purpose purpose, List<String> sourceCidrs, List<String> destCidrs, Integer icmpCode, Integer icmpType, Long related, TrafficType trafficType) {
|
||||
this(xId,ipAddressId, portStart, portEnd, protocol, networkId, accountId, domainId, purpose, sourceCidrs, icmpCode, icmpType, related, trafficType);
|
||||
this.destinationCidrs = destCidrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("Rule[").append(id).append("-").append(purpose).append("-").append(state).append("]").toString();
|
||||
|
||||
@ -81,6 +81,7 @@ public class Upgrade4930to41000 implements DbUpgrade {
|
||||
public void performDataMigration(Connection conn) {
|
||||
updateSystemVmTemplates(conn);
|
||||
populateGuestOsDetails(conn);
|
||||
updateSourceCidrs(conn);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ -493,4 +494,17 @@ public class Upgrade4930to41000 implements DbUpgrade {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateSourceCidrs(Connection conn){
|
||||
//with ipset the value for source cidr 0.0.0.0/0 can't be added in ipset. So changing it to network cidr.
|
||||
try(PreparedStatement pstmt = conn.prepareStatement("UPDATE `cloud`.`firewall_rules_cidrs` AS s, (SELECT IFNULL(networks.network_cidr,networks.cidr) cidr," +
|
||||
"`firewall_rules_cidrs`.`id`, `firewall_rules`.`traffic_type` "+
|
||||
"FROM `cloud`.`networks`, `cloud`.`firewall_rules`,`cloud`.`firewall_rules_cidrs` WHERE `cloud`.`networks`.`id`=`cloud`.`firewall_rules`.`network_id` " +
|
||||
"AND `cloud`.`firewall_rules`.`id` = `cloud`.`firewall_rules_cidrs`.`firewall_rule_id`) AS p " +
|
||||
"SET `s`.`source_cidr` = `p`.`cidr` WHERE `s`.`source_cidr`=\"0.0.0.0/0\" AND `s`.`id`=`p`.`id` AND `p`.`traffic_type`=\"Egress\" ;")){
|
||||
pstmt.execute();
|
||||
}catch (SQLException e) {
|
||||
throw new CloudRuntimeException("updateSourceCidrs:Exception:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,6 +311,7 @@ import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.network.dao.FirewallRulesDcidrsDao;
|
||||
|
||||
public class ApiDBUtils {
|
||||
private static ManagementServer s_ms;
|
||||
@ -371,6 +372,7 @@ public class ApiDBUtils {
|
||||
static ConfigurationDao s_configDao;
|
||||
static ConsoleProxyDao s_consoleProxyDao;
|
||||
static FirewallRulesCidrsDao s_firewallCidrsDao;
|
||||
static FirewallRulesDcidrsDao s_firewallDcidrsDao;
|
||||
static VMInstanceDao s_vmDao;
|
||||
static ResourceLimitService s_resourceLimitMgr;
|
||||
static ProjectService s_projectMgr;
|
||||
@ -543,6 +545,8 @@ public class ApiDBUtils {
|
||||
@Inject
|
||||
private FirewallRulesCidrsDao firewallCidrsDao;
|
||||
@Inject
|
||||
private FirewallRulesDcidrsDao firewalDcidrsDao;
|
||||
@Inject
|
||||
private VMInstanceDao vmDao;
|
||||
@Inject
|
||||
private ResourceLimitService resourceLimitMgr;
|
||||
@ -718,6 +722,7 @@ public class ApiDBUtils {
|
||||
s_configDao = configDao;
|
||||
s_consoleProxyDao = consoleProxyDao;
|
||||
s_firewallCidrsDao = firewallCidrsDao;
|
||||
s_firewallDcidrsDao = firewalDcidrsDao;
|
||||
s_vmDao = vmDao;
|
||||
s_resourceLimitMgr = resourceLimitMgr;
|
||||
s_projectMgr = projectMgr;
|
||||
@ -1303,6 +1308,10 @@ public class ApiDBUtils {
|
||||
return s_firewallCidrsDao.getSourceCidrs(id);
|
||||
}
|
||||
|
||||
public static List<String> findFirewallDestCidrs(long id){
|
||||
return s_firewallDcidrsDao.getDestCidrs(id);
|
||||
}
|
||||
|
||||
public static Account getProjectOwner(long projectId) {
|
||||
return s_projectMgr.getProjectOwner(projectId);
|
||||
}
|
||||
|
||||
@ -2216,6 +2216,11 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
|
||||
response.setCidrList(StringUtils.join(cidrs, ","));
|
||||
|
||||
if(fwRule.getTrafficType() == FirewallRule.TrafficType.Egress){
|
||||
List<String> destCidrs = ApiDBUtils.findFirewallDestCidrs(fwRule.getId());
|
||||
response.setDestCidr(StringUtils.join(destCidrs,","));
|
||||
}
|
||||
|
||||
if (fwRule.getTrafficType() == FirewallRule.TrafficType.Ingress) {
|
||||
IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
|
||||
response.setPublicIpAddressId(ip.getUuid());
|
||||
|
||||
@ -22,10 +22,12 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.network.dao.FirewallRulesDcidrsDao;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -111,6 +113,8 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
@Inject
|
||||
FirewallRulesCidrsDao _firewallCidrsDao;
|
||||
@Inject
|
||||
FirewallRulesDcidrsDao _firewallDcidrsDao;
|
||||
@Inject
|
||||
AccountManager _accountMgr;
|
||||
@Inject
|
||||
NetworkOrchestrationService _networkMgr;
|
||||
@ -172,7 +176,11 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
throw new InvalidParameterValueException("Egress firewall rules are not supported for " + network.getGuestType() + " networks");
|
||||
}
|
||||
|
||||
return createFirewallRule(null, caller, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(),
|
||||
List<String> sourceCidrs = rule.getSourceCidrList();
|
||||
if (sourceCidrs != null && !sourceCidrs.isEmpty())
|
||||
Collections.replaceAll(sourceCidrs, "0.0.0.0/0", network.getCidr());
|
||||
|
||||
return createFirewallRule(null, caller, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), sourceCidrs, rule.getDestinationCidrList(),
|
||||
rule.getIcmpCode(), rule.getIcmpType(), null, rule.getType(), rule.getNetworkId(), rule.getTrafficType(), rule.isDisplay());
|
||||
}
|
||||
|
||||
@ -183,12 +191,12 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
Long sourceIpAddressId = rule.getSourceIpAddressId();
|
||||
|
||||
return createFirewallRule(sourceIpAddressId, caller, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(),
|
||||
rule.getSourceCidrList(), rule.getIcmpCode(), rule.getIcmpType(), null, rule.getType(), rule.getNetworkId(), rule.getTrafficType(), rule.isDisplay());
|
||||
rule.getSourceCidrList(), null, rule.getIcmpCode(), rule.getIcmpType(), null, rule.getType(), rule.getNetworkId(), rule.getTrafficType(), rule.isDisplay());
|
||||
}
|
||||
|
||||
//Destination CIDR capability is currently implemented for egress rules only. For others, the field is passed as null.
|
||||
@DB
|
||||
protected FirewallRule createFirewallRule(final Long ipAddrId, Account caller, final String xId, final Integer portStart, final Integer portEnd,
|
||||
final String protocol, final List<String> sourceCidrList, final Integer icmpCode, final Integer icmpType, final Long relatedRuleId,
|
||||
final String protocol, final List<String> sourceCidrList, final List<String> destCidrList, final Integer icmpCode, final Integer icmpType, final Long relatedRuleId,
|
||||
final FirewallRule.FirewallRuleType type,
|
||||
final Long networkId, final FirewallRule.TrafficType trafficType, final Boolean forDisplay) throws NetworkRuleConflictException {
|
||||
|
||||
@ -234,24 +242,24 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
@Override
|
||||
public FirewallRuleVO doInTransaction(TransactionStatus status) throws NetworkRuleConflictException {
|
||||
FirewallRuleVO newRule =
|
||||
new FirewallRuleVO(xId, ipAddrId, portStart, portEnd, protocol.toLowerCase(), networkId, accountIdFinal, domainIdFinal, Purpose.Firewall,
|
||||
sourceCidrList, icmpCode, icmpType, relatedRuleId, trafficType);
|
||||
newRule.setType(type);
|
||||
new FirewallRuleVO(xId, ipAddrId, portStart, portEnd, protocol.toLowerCase(), networkId, accountIdFinal, domainIdFinal, Purpose.Firewall,
|
||||
sourceCidrList, destCidrList, icmpCode, icmpType, relatedRuleId, trafficType);
|
||||
newRule.setType(type);
|
||||
if (forDisplay != null) {
|
||||
newRule.setDisplay(forDisplay);
|
||||
}
|
||||
newRule = _firewallDao.persist(newRule);
|
||||
newRule = _firewallDao.persist(newRule);
|
||||
|
||||
if (type == FirewallRuleType.User)
|
||||
detectRulesConflict(newRule);
|
||||
if (type == FirewallRuleType.User)
|
||||
detectRulesConflict(newRule);
|
||||
|
||||
if (!_firewallDao.setStateToAdd(newRule)) {
|
||||
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
|
||||
}
|
||||
CallContext.current().setEventDetails("Rule Id: " + newRule.getId());
|
||||
if (!_firewallDao.setStateToAdd(newRule)) {
|
||||
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
|
||||
}
|
||||
CallContext.current().setEventDetails("Rule Id: " + newRule.getId());
|
||||
|
||||
return newRule;
|
||||
}
|
||||
return newRule;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -340,6 +348,17 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
return new Pair<List<? extends FirewallRule>, Integer>(result.first(), result.second());
|
||||
}
|
||||
|
||||
//Intermediate funciton used in detectRulesConflict to check for the conflicting cidrs in the rules already applied and the newRule being applied.
|
||||
boolean detectConflictingCidrs(List<String> cidrList1, List<String> cidrList2){
|
||||
if(cidrList1.isEmpty() && cidrList2.isEmpty()){
|
||||
return true;
|
||||
}
|
||||
|
||||
Collection<String> similar = new HashSet<String>(cidrList1);
|
||||
similar.retainAll(cidrList2);
|
||||
return (similar.size()>0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflictException {
|
||||
List<FirewallRuleVO> rules;
|
||||
@ -366,23 +385,16 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
boolean bothRulesFirewall = (rule.getPurpose() == newRule.getPurpose() && rule.getPurpose() == Purpose.Firewall);
|
||||
boolean duplicatedCidrs = false;
|
||||
if (bothRulesFirewall) {
|
||||
// Verify that the rules have different cidrs
|
||||
_firewallDao.loadSourceCidrs(rule);
|
||||
_firewallDao.loadSourceCidrs((FirewallRuleVO)newRule);
|
||||
|
||||
List<String> ruleCidrList = rule.getSourceCidrList();
|
||||
List<String> newRuleCidrList = newRule.getSourceCidrList();
|
||||
_firewallDao.loadDestinationCidrs(rule);
|
||||
_firewallDao.loadDestinationCidrs((FirewallRuleVO) newRule);
|
||||
|
||||
if (ruleCidrList == null || newRuleCidrList == null) {
|
||||
if (rule.getSourceCidrList() == null || newRule.getSourceCidrList() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Collection<String> similar = new HashSet<String>(ruleCidrList);
|
||||
similar.retainAll(newRuleCidrList);
|
||||
|
||||
if (similar.size() > 0) {
|
||||
duplicatedCidrs = true;
|
||||
}
|
||||
duplicatedCidrs = (detectConflictingCidrs(rule.getSourceCidrList(), newRule.getSourceCidrList()) && detectConflictingCidrs(rule.getDestinationCidrList(), newRule.getDestinationCidrList()));
|
||||
}
|
||||
|
||||
if (!oneOfRulesIsFirewall) {
|
||||
@ -393,10 +405,12 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
}
|
||||
}
|
||||
|
||||
// Checking if the rule applied is to the same network that is passed in the rule.
|
||||
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());
|
||||
}
|
||||
|
||||
//Check for the ICMP protocol. This has to be done separately from other protocols as we need to check the ICMP codes and ICMP type also.
|
||||
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()) && duplicatedCidrs) {
|
||||
@ -408,10 +422,12 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
(newRule.getSourcePortStart() != null && newRule.getSourcePortEnd() != null && rule.getSourcePortStart() != null && rule.getSourcePortEnd() != null);
|
||||
boolean nullPorts =
|
||||
(newRule.getSourcePortStart() == null && newRule.getSourcePortEnd() == null && rule.getSourcePortStart() == null && rule.getSourcePortEnd() == null);
|
||||
if(nullPorts && duplicatedCidrs && (rule.getProtocol().equalsIgnoreCase(newRule.getProtocol())) && !newRule.getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO))
|
||||
{
|
||||
|
||||
// If ports are not specified and cidrs are same and protocol is also same(NOT ICMP as it is separately checked above)
|
||||
if(nullPorts && duplicatedCidrs && (rule.getProtocol().equalsIgnoreCase(newRule.getProtocol())) && !newRule.getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
|
||||
throw new NetworkRuleConflictException("There is already a firewall rule specified with protocol = " +newRule.getProtocol()+ " and no ports");
|
||||
}
|
||||
|
||||
if (!notNullPorts) {
|
||||
continue;
|
||||
} else if (!oneOfRulesIsFirewall &&
|
||||
@ -424,6 +440,7 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
newRule.getSourcePortEnd().intValue() >= rule.getSourcePortStart().intValue()) ||
|
||||
(newRule.getSourcePortStart().intValue() <= rule.getSourcePortEnd().intValue() &&
|
||||
newRule.getSourcePortEnd().intValue() >= rule.getSourcePortEnd().intValue()))) {
|
||||
//Above else if conditions checks for the conflicting port ranges.
|
||||
|
||||
// we allow port forwarding rules with the same parameters but different protocols
|
||||
boolean allowPf =
|
||||
@ -657,6 +674,7 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
for (FirewallRuleVO rule : rules) {
|
||||
// load cidrs if any
|
||||
rule.setSourceCidrList(_firewallCidrsDao.getSourceCidrs(rule.getId()));
|
||||
rule.setDestinationCidrsList(_firewallDcidrsDao.getDestCidrs(rule.getId()));
|
||||
}
|
||||
|
||||
if (caller != null) {
|
||||
@ -682,10 +700,14 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
|
||||
NetworkVO network = _networkDao.findById(networkId);
|
||||
List<String> sourceCidr = new ArrayList<String>();
|
||||
List<String> destCidr = new ArrayList<String>();
|
||||
|
||||
|
||||
sourceCidr.add(network.getCidr());
|
||||
destCidr.add(NetUtils.ALL_CIDRS);
|
||||
|
||||
sourceCidr.add(NetUtils.ALL_CIDRS);
|
||||
FirewallRuleVO ruleVO =
|
||||
new FirewallRuleVO(null, null, null, null, "all", networkId, network.getAccountId(), network.getDomainId(), Purpose.Firewall, sourceCidr, null, null, null,
|
||||
new FirewallRuleVO(null, null, null, null, "all", networkId, network.getAccountId(), network.getDomainId(), Purpose.Firewall, sourceCidr, destCidr, null, null, null,
|
||||
FirewallRule.TrafficType.Egress, FirewallRuleType.System);
|
||||
ruleVO.setState(add ? State.Add : State.Revoke);
|
||||
List<FirewallRuleVO> rules = new ArrayList<FirewallRuleVO>();
|
||||
@ -884,7 +906,7 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
|
||||
List<String> oneCidr = new ArrayList<String>();
|
||||
oneCidr.add(NetUtils.ALL_CIDRS);
|
||||
return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, icmpCode, icmpType, relatedRuleId, FirewallRule.FirewallRuleType.User,
|
||||
return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, null, icmpCode, icmpType, relatedRuleId, FirewallRule.FirewallRuleType.User,
|
||||
networkId, FirewallRule.TrafficType.Ingress, true);
|
||||
}
|
||||
|
||||
@ -998,7 +1020,7 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
||||
if (rule.getSourceCidrList() == null && (rule.getPurpose() == Purpose.Firewall || rule.getPurpose() == Purpose.NetworkACL)) {
|
||||
_firewallDao.loadSourceCidrs(rule);
|
||||
}
|
||||
createFirewallRule(ip.getId(), acct, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(),
|
||||
createFirewallRule(ip.getId(), acct, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(),null,
|
||||
rule.getIcmpCode(), rule.getIcmpType(), rule.getRelated(), FirewallRuleType.System, rule.getNetworkId(), rule.getTrafficType(), true);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to add system wide firewall rule, due to:" + e.toString());
|
||||
|
||||
@ -441,6 +441,7 @@ public class CommandSetupHelper {
|
||||
}
|
||||
for (final FirewallRule rule : rules) {
|
||||
_rulesDao.loadSourceCidrs((FirewallRuleVO) rule);
|
||||
_rulesDao.loadDestinationCidrs((FirewallRuleVO)rule);
|
||||
final FirewallRule.TrafficType traffictype = rule.getTrafficType();
|
||||
if (traffictype == FirewallRule.TrafficType.Ingress) {
|
||||
final IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
|
||||
|
||||
@ -1948,10 +1948,13 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
|
||||
// The default on the router is set to Deny all. So, if the default configuration in the offering is set to true (Allow), we change the Egress here
|
||||
if (defaultEgressPolicy) {
|
||||
final List<String> sourceCidr = new ArrayList<String>();
|
||||
final List<String> destCidr = new ArrayList<String>();
|
||||
|
||||
sourceCidr.add(network.getCidr());
|
||||
destCidr.add(NetUtils.ALL_CIDRS);
|
||||
|
||||
sourceCidr.add(NetUtils.ALL_CIDRS);
|
||||
final FirewallRule rule = new FirewallRuleVO(null, null, null, null, "all", networkId, network.getAccountId(), network.getDomainId(), Purpose.Firewall, sourceCidr,
|
||||
null, null, null, FirewallRule.TrafficType.Egress, FirewallRule.FirewallRuleType.System);
|
||||
destCidr, null, null, null, FirewallRule.TrafficType.Egress, FirewallRule.FirewallRuleType.System);
|
||||
|
||||
rules.add(rule);
|
||||
} else {
|
||||
|
||||
@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
@ -189,9 +190,17 @@ public class FirewallManagerTest {
|
||||
FirewallRuleVO rule2 = spy(new FirewallRuleVO("rule2", 3, 1701, "UDP", 1, 2, 1, Purpose.Vpn, null, null, null, null));
|
||||
FirewallRuleVO rule3 = spy(new FirewallRuleVO("rule3", 3, 4500, "UDP", 1, 2, 1, Purpose.Vpn, null, null, null, null));
|
||||
|
||||
List<String> sString = Arrays.asList("10.1.1.1/24","192.168.1.1/24");
|
||||
List<String> dString1 = Arrays.asList("10.1.1.1/25");
|
||||
List<String> dString2 = Arrays.asList("10.1.1.128/25");
|
||||
|
||||
FirewallRuleVO rule4 = spy(new FirewallRuleVO("rule4", 3L, 10, 20, "TCP", 1, 2, 1, Purpose.Firewall, sString, dString1, null, null,
|
||||
null, FirewallRule.TrafficType.Egress));
|
||||
|
||||
ruleList.add(rule1);
|
||||
ruleList.add(rule2);
|
||||
ruleList.add(rule3);
|
||||
ruleList.add(rule4);
|
||||
|
||||
FirewallManagerImpl firewallMgr = (FirewallManagerImpl)_firewallMgr;
|
||||
|
||||
@ -199,15 +208,19 @@ public class FirewallManagerTest {
|
||||
when(rule1.getId()).thenReturn(1L);
|
||||
when(rule2.getId()).thenReturn(2L);
|
||||
when(rule3.getId()).thenReturn(3L);
|
||||
when(rule4.getId()).thenReturn(4L);
|
||||
|
||||
FirewallRule newRule1 = new FirewallRuleVO("newRule1", 3, 500, "TCP", 1, 2, 1, Purpose.PortForwarding, null, null, null, null);
|
||||
FirewallRule newRule2 = new FirewallRuleVO("newRule2", 3, 1701, "TCP", 1, 2, 1, Purpose.PortForwarding, null, null, null, null);
|
||||
FirewallRule newRule3 = new FirewallRuleVO("newRule3", 3, 4500, "TCP", 1, 2, 1, Purpose.PortForwarding, null, null, null, null);
|
||||
FirewallRule newRule4 = new FirewallRuleVO("newRule4", 3L, 15, 25, "TCP", 1, 2, 1, Purpose.Firewall, sString, dString2, null, null,
|
||||
null, FirewallRule.TrafficType.Egress);
|
||||
|
||||
try {
|
||||
firewallMgr.detectRulesConflict(newRule1);
|
||||
firewallMgr.detectRulesConflict(newRule2);
|
||||
firewallMgr.detectRulesConflict(newRule3);
|
||||
firewallMgr.detectRulesConflict(newRule4);
|
||||
}
|
||||
catch (NetworkRuleConflictException ex) {
|
||||
Assert.fail();
|
||||
|
||||
@ -19,6 +19,7 @@ package org.apache.cloudstack.networkoffering;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.cloud.network.dao.FirewallRulesDcidrsDaoImpl;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -131,7 +132,7 @@ import com.cloud.vm.dao.VMInstanceDaoImpl;
|
||||
DiskOfferingDaoImpl.class, DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class,
|
||||
DataCenterDetailsDaoImpl.class, NicSecondaryIpDaoImpl.class, UserIpv6AddressDaoImpl.class, UserDaoImpl.class, NicDaoImpl.class,
|
||||
NetworkDomainDaoImpl.class, HostDetailsDaoImpl.class, HostTagsDaoImpl.class, ClusterDaoImpl.class, FirewallRulesDaoImpl.class,
|
||||
FirewallRulesCidrsDaoImpl.class, PhysicalNetworkDaoImpl.class, PhysicalNetworkTrafficTypeDaoImpl.class, PhysicalNetworkServiceProviderDaoImpl.class,
|
||||
FirewallRulesCidrsDaoImpl.class, FirewallRulesDcidrsDaoImpl.class, PhysicalNetworkDaoImpl.class, PhysicalNetworkTrafficTypeDaoImpl.class, PhysicalNetworkServiceProviderDaoImpl.class,
|
||||
LoadBalancerDaoImpl.class, NetworkServiceMapDaoImpl.class, PrimaryDataStoreDaoImpl.class, StoragePoolDetailsDaoImpl.class,
|
||||
PortableIpRangeDaoImpl.class, RegionDaoImpl.class, PortableIpDaoImpl.class, AccountGuestVlanMapDaoImpl.class, ImageStoreDaoImpl.class, ImageStoreDetailsDaoImpl.class},
|
||||
includeFilters = {@Filter(value = ChildTestConfiguration.Library.class, type = FilterType.CUSTOM)},
|
||||
|
||||
@ -246,3 +246,12 @@ CREATE TABLE `cloud`.`guest_os_details` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `user_ip_address` ADD COLUMN `rule_state` VARCHAR(32) COMMENT 'static rule state while removing';
|
||||
CREATE TABLE `cloud`.`firewall_rules_dcidrs`(
|
||||
`id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`firewall_rule_id` BIGINT(20) unsigned NOT NULL,
|
||||
`destination_cidr` VARCHAR(18) DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY `unique_rule_dcidrs` (`firewall_rule_id`, `destination_cidr`),
|
||||
KEY `fk_firewall_dcidrs_firewall_rules` (`firewall_rule_id`),
|
||||
CONSTRAINT `fk_firewall_dcidrs_firewall_rules` FOREIGN KEY (`firewall_rule_id`) REFERENCES `firewall_rules` (`id`) ON DELETE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
@ -100,18 +100,26 @@ class CsAcl(CsDataBag):
|
||||
self.rule['allowed'] = True
|
||||
self.rule['action'] = "ACCEPT"
|
||||
|
||||
if self.rule['type'] == 'all' and not obj['source_cidr_list']:
|
||||
self.rule['cidr'] = ['0.0.0.0/0']
|
||||
if self.rule['type'] == 'all' and obj['source_cidr_list']:
|
||||
self.rule['cidr'] = []
|
||||
else:
|
||||
self.rule['cidr'] = obj['source_cidr_list']
|
||||
|
||||
if self.direction == 'egress':
|
||||
try:
|
||||
if not obj['dest_cidr_list']:
|
||||
self.rule['dcidr'] = []
|
||||
else:
|
||||
self.rule['dcidr'] = obj['dest_cidr_list']
|
||||
except Exception:
|
||||
self.rule['dcidr'] = []
|
||||
|
||||
logging.debug("AclIP created for rule ==> %s", self.rule)
|
||||
|
||||
def create(self):
|
||||
for cidr in self.rule['cidr']:
|
||||
self.add_rule(cidr)
|
||||
self.add_rule()
|
||||
|
||||
def add_rule(self, cidr):
|
||||
def add_rule(self):
|
||||
icmp_type = ''
|
||||
rule = self.rule
|
||||
icmp_type = "any"
|
||||
@ -126,24 +134,48 @@ class CsAcl(CsDataBag):
|
||||
if "first_port" in self.rule.keys() and \
|
||||
self.rule['first_port'] != self.rule['last_port']:
|
||||
rnge = " --dport %s:%s" % (rule['first_port'], rule['last_port'])
|
||||
if self.direction == 'ingress':
|
||||
if rule['protocol'] == "icmp":
|
||||
self.fw.append(["mangle", "front",
|
||||
" -A FIREWALL_%s" % self.ip +
|
||||
" -s %s " % cidr +
|
||||
" -p %s " % rule['protocol'] +
|
||||
" -m %s " % rule['protocol'] +
|
||||
" --icmp-type %s -j %s" % (icmp_type, self.rule['action'])])
|
||||
else:
|
||||
self.fw.append(["mangle", "front",
|
||||
" -A FIREWALL_%s" % self.ip +
|
||||
" -s %s " % cidr +
|
||||
" -p %s " % rule['protocol'] +
|
||||
" -m %s " % rule['protocol'] +
|
||||
" %s -j RETURN" % rnge])
|
||||
|
||||
logging.debug("Current ACL IP direction is ==> %s", self.direction)
|
||||
|
||||
if self.direction == 'ingress':
|
||||
for cidr in self.rule['cidr']:
|
||||
if rule['protocol'] == "icmp":
|
||||
self.fw.append(["mangle", "front",
|
||||
" -A FIREWALL_%s" % self.ip +
|
||||
" -s %s " % cidr +
|
||||
" -p %s " % rule['protocol'] +
|
||||
" --icmp-type %s -j %s" % (icmp_type, self.rule['action'])])
|
||||
else:
|
||||
self.fw.append(["mangle", "front",
|
||||
" -A FIREWALL_%s" % self.ip +
|
||||
" -s %s " % cidr +
|
||||
" -p %s " % rule['protocol'] +
|
||||
" %s -j RETURN" % rnge])
|
||||
|
||||
sflag=False
|
||||
dflag=False
|
||||
if self.direction == 'egress':
|
||||
ruleId = self.rule['id']
|
||||
sourceIpsetName = 'sourceCidrIpset-%d' %ruleId
|
||||
destIpsetName = 'destCidrIpset-%d' %ruleId
|
||||
|
||||
#create source cidr ipset
|
||||
srcIpset = 'ipset create '+sourceIpsetName + ' hash:net '
|
||||
dstIpset = 'ipset create '+destIpsetName + ' hash:net '
|
||||
|
||||
CsHelper.execute(srcIpset)
|
||||
CsHelper.execute(dstIpset)
|
||||
for cidr in self.rule['cidr']:
|
||||
ipsetAddCmd = 'ipset add '+ sourceIpsetName + ' '+cidr
|
||||
CsHelper.execute(ipsetAddCmd)
|
||||
sflag = True
|
||||
|
||||
logging.debug("egress rule ####==> %s", self.rule)
|
||||
for cidr in self.rule['dcidr']:
|
||||
ipsetAddCmd = 'ipset add '+ destIpsetName + ' '+cidr
|
||||
CsHelper.execute(ipsetAddCmd)
|
||||
dflag = True
|
||||
|
||||
self.fw.append(["filter", "", " -A FW_OUTBOUND -j FW_EGRESS_RULES"])
|
||||
|
||||
fwr = " -I FW_EGRESS_RULES"
|
||||
@ -165,16 +197,23 @@ class CsAcl(CsDataBag):
|
||||
else:
|
||||
self.rule['action'] = "ACCEPT"
|
||||
|
||||
egressIpsetStr=''
|
||||
if sflag == True and dflag == True:
|
||||
egressIpsetStr = " -m set --match-set %s src " % sourceIpsetName + \
|
||||
" -m set --match-set %s dst " % destIpsetName
|
||||
elif sflag == True:
|
||||
egressIpsetStr = " -m set --match-set %s src " % sourceIpsetName
|
||||
elif dflag == True:
|
||||
egressIpsetStr = " -m set --match-set %s dst " % destIpsetName
|
||||
|
||||
if rule['protocol'] == "icmp":
|
||||
fwr += " -s %s " % cidr + \
|
||||
" -p %s " % rule['protocol'] + \
|
||||
fwr += egressIpsetStr + " -p %s " % rule['protocol'] + " -m %s " % rule['protocol'] + \
|
||||
" --icmp-type %s" % icmp_type
|
||||
elif rule['protocol'] != "all":
|
||||
fwr += " -s %s " % cidr + \
|
||||
" -p %s " % rule['protocol'] + \
|
||||
" %s" % rnge
|
||||
fwr += egressIpsetStr + " -p %s " % rule['protocol'] + " -m %s " % rule['protocol'] + \
|
||||
" %s" % rnge
|
||||
elif rule['protocol'] == "all":
|
||||
fwr += " -s %s " % cidr
|
||||
fwr += egressIpsetStr
|
||||
|
||||
self.fw.append(["filter", "", "%s -j %s" % (fwr, rule['action'])])
|
||||
logging.debug("EGRESS rule configured for protocol ==> %s, action ==> %s", rule['protocol'], rule['action'])
|
||||
@ -265,6 +304,9 @@ class CsAcl(CsDataBag):
|
||||
# Ensure that FW_EGRESS_RULES chain exists
|
||||
CsHelper.execute("iptables-save | grep '^:FW_EGRESS_RULES' || iptables -t filter -N FW_EGRESS_RULES")
|
||||
CsHelper.execute("iptables-save | grep '^-A FW_EGRESS_RULES -j ACCEPT$' | sed 's/^-A/iptables -t filter -D/g' | bash")
|
||||
CsHelper.execute("iptables -F FW_EGRESS_RULES")
|
||||
CsHelper.execute("ipset -L | grep Name: | awk {'print $2'} | ipset flush")
|
||||
CsHelper.execute("ipset -L | grep Name: | awk {'print $2'} | ipset destroy")
|
||||
|
||||
def process(self):
|
||||
for item in self.dbag:
|
||||
|
||||
@ -67,6 +67,7 @@ function install_packages() {
|
||||
xenstore-utils libxenstore3.0 \
|
||||
conntrackd ipvsadm libnetfilter-conntrack3 libnl-3-200 libnl-genl-3-200 \
|
||||
ipcalc \
|
||||
ipset \
|
||||
iptables-persistent \
|
||||
libtcnative-1 libssl-dev libapr1-dev \
|
||||
python-flask \
|
||||
|
||||
@ -8223,6 +8223,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
|
||||
|
||||
.multi-edit th.add-rule,
|
||||
.multi-edit td.add-rule {
|
||||
border-right: 1px solid #cdcccc;
|
||||
}
|
||||
|
||||
.multi-edit .data-table td.add-vm:hover {
|
||||
|
||||
@ -512,6 +512,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
|
||||
"label.cidr":"CIDR",
|
||||
"label.cidr.account":"CIDR or Account/Security Group",
|
||||
"label.cidr.list":"Source CIDR",
|
||||
"label.cidr.destination.list":"Destination CIDR",
|
||||
"label.cisco.nexus1000v.ip.address":"Nexus 1000v IP Address",
|
||||
"label.cisco.nexus1000v.password":"Nexus 1000v Password",
|
||||
"label.cisco.nexus1000v.username":"Nexus 1000v Username",
|
||||
|
||||
@ -1397,6 +1397,11 @@
|
||||
label: 'label.cidr.list',
|
||||
isOptional: true
|
||||
},
|
||||
'destcidrlist': {
|
||||
edit: true,
|
||||
label: 'label.cidr.destination.list',
|
||||
isOptional: true
|
||||
},
|
||||
'protocol': {
|
||||
label: 'label.protocol',
|
||||
select: function(args) {
|
||||
@ -1414,6 +1419,7 @@
|
||||
var name = $(this).attr('rel');
|
||||
|
||||
return name != 'cidrlist' &&
|
||||
name != 'destcidrlist' &&
|
||||
name != 'icmptype' &&
|
||||
name != 'icmpcode' &&
|
||||
name != 'protocol' &&
|
||||
@ -1482,6 +1488,7 @@
|
||||
var data = {
|
||||
protocol: args.data.protocol,
|
||||
cidrlist: args.data.cidrlist,
|
||||
destcidrlist: args.data.destcidrlist,
|
||||
networkid: args.context.networks[0].id
|
||||
};
|
||||
|
||||
@ -1582,7 +1589,9 @@
|
||||
rule.endport = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if(!rule.destcidrlist){
|
||||
rule.destcidrlist = ' ';
|
||||
}
|
||||
return rule;
|
||||
})
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user