From 2984b0607f0e0a0309c2fa02dd7841e5a1bd23f3 Mon Sep 17 00:00:00 2001 From: Abhinandan Prateek Date: Mon, 9 May 2011 17:41:50 +0530 Subject: [PATCH] bug 8115: source ip filtering Created a table for source cidrs list. Created necessary Daos and VOs. Updated PortForwardingRulesDao to persist/update non null list of cidrs. For deletion depending on ON DELETE CASCADE. --- .../commands/CreatePortForwardingRuleCmd.java | 11 +++ .../network/rules/PortForwardingRule.java | 10 ++- .../cloud/network/FirewallRulesCidrsVO.java | 61 ++++++++++++++++ .../network/dao/FirewallRulesCidrsDao.java | 32 +++++++++ .../dao/FirewallRulesCidrsDaoImpl.java | 71 +++++++++++++++++++ .../network/rules/PortForwardingRuleVO.java | 33 +++++++-- .../cloud/network/rules/RulesManagerImpl.java | 6 +- .../rules/dao/PortForwardingRulesDaoImpl.java | 60 ++++++++++++++++ setup/db/create-schema.sql | 10 +++ 9 files changed, 283 insertions(+), 11 deletions(-) create mode 100644 server/src/com/cloud/network/FirewallRulesCidrsVO.java create mode 100644 server/src/com/cloud/network/dao/FirewallRulesCidrsDao.java create mode 100644 server/src/com/cloud/network/dao/FirewallRulesCidrsDaoImpl.java diff --git a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java index 672f228ec1a..744d6e5f631 100644 --- a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java +++ b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java @@ -18,6 +18,8 @@ package com.cloud.api.commands; +import java.util.List; + import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -27,6 +29,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.FirewallRuleResponse; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -62,6 +65,10 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.LONG, required = true, description = "the ID of the virtual machine for the port forwarding rule") private Long virtualMachineId; + + @Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from") + private List cidrlist; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// @@ -89,6 +96,10 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P return virtualMachineId; } + public List getSourceCidrList() { + return cidrlist; + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// diff --git a/api/src/com/cloud/network/rules/PortForwardingRule.java b/api/src/com/cloud/network/rules/PortForwardingRule.java index bff8d10d86b..0da49c657ad 100644 --- a/api/src/com/cloud/network/rules/PortForwardingRule.java +++ b/api/src/com/cloud/network/rules/PortForwardingRule.java @@ -17,6 +17,8 @@ */ package com.cloud.network.rules; +import java.util.List; + import com.cloud.utils.net.Ip; /** @@ -41,6 +43,12 @@ public interface PortForwardingRule extends FirewallRule { /** * @return destination ip address. */ - long getVirtualMachineId(); + long getVirtualMachineId(); + /** + * @return source cidr to forward + */ + List getSourceCidrList(); + + } diff --git a/server/src/com/cloud/network/FirewallRulesCidrsVO.java b/server/src/com/cloud/network/FirewallRulesCidrsVO.java new file mode 100644 index 00000000000..fde8d879b1b --- /dev/null +++ b/server/src/com/cloud/network/FirewallRulesCidrsVO.java @@ -0,0 +1,61 @@ +/** + * 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 . + * + */ + +package com.cloud.network; + +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_cidrs")) +public class FirewallRulesCidrsVO { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private Long id; + + @Column(name="firewall_rule_id") + private long firewallRuleId; + + @Column(name="source_cidr") + private String sourceCidrList; + + public FirewallRulesCidrsVO() { } + + public FirewallRulesCidrsVO(long firewallRuleId, String sourceCidrList) { + this.firewallRuleId = firewallRuleId; + this.sourceCidrList = sourceCidrList; + } + + public Long getId() { + return id; + } + + public long getFirewallRuleId() { + return firewallRuleId; + } + + public String getCidr() { + return sourceCidrList; + } + +} diff --git a/server/src/com/cloud/network/dao/FirewallRulesCidrsDao.java b/server/src/com/cloud/network/dao/FirewallRulesCidrsDao.java new file mode 100644 index 00000000000..27c33961467 --- /dev/null +++ b/server/src/com/cloud/network/dao/FirewallRulesCidrsDao.java @@ -0,0 +1,32 @@ +/** + * 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 . + * + */ + +package com.cloud.network.dao; + +import java.util.List; + +import com.cloud.network.FirewallRulesCidrsVO; +import com.cloud.utils.db.GenericDao; + +public interface FirewallRulesCidrsDao extends GenericDao { + + void persist(long firewallRuleId, List sourceCidrs); + + List getSourceCidrs(long firewallRuleId); + +} diff --git a/server/src/com/cloud/network/dao/FirewallRulesCidrsDaoImpl.java b/server/src/com/cloud/network/dao/FirewallRulesCidrsDaoImpl.java new file mode 100644 index 00000000000..2eee096d1bf --- /dev/null +++ b/server/src/com/cloud/network/dao/FirewallRulesCidrsDaoImpl.java @@ -0,0 +1,71 @@ +/* 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 . + * + */ + +package com.cloud.network.dao; + +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.network.FirewallRulesCidrsVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; + + +@Local(value=FirewallRulesCidrsDaoImpl.class) +public class FirewallRulesCidrsDaoImpl extends GenericDaoBase implements FirewallRulesCidrsDao { + private static final Logger s_logger = Logger.getLogger(FirewallRulesCidrsDaoImpl.class); + protected final SearchBuilder CidrsSearch; + + protected FirewallRulesCidrsDaoImpl() { + CidrsSearch = createSearchBuilder(); + CidrsSearch.and("firewallRuleId", CidrsSearch.entity().getFirewallRuleId(), SearchCriteria.Op.EQ); + CidrsSearch.done(); + } + + @Override + public List getSourceCidrs(long firewallRuleId) { + SearchCriteria sc = CidrsSearch.create(); + sc.setParameters("firewallRuleId", firewallRuleId); + + List results = search(sc, null); + List hostTags = new ArrayList(results.size()); + for (FirewallRulesCidrsVO result : results) { + hostTags.add(result.getCidr()); + } + + return hostTags; + } + + @Override + public void persist(long firewallRuleId, List sourceCidrs) { + Transaction txn = Transaction.currentTxn(); + + txn.start(); + for (String tag : sourceCidrs) { + s_logger.info("Saving cidrs " + tag); + FirewallRulesCidrsVO vo = new FirewallRulesCidrsVO(firewallRuleId, tag); + persist(vo); + } + txn.commit(); + } +} diff --git a/server/src/com/cloud/network/rules/PortForwardingRuleVO.java b/server/src/com/cloud/network/rules/PortForwardingRuleVO.java index 057d9fd5055..dbb4f339fe6 100644 --- a/server/src/com/cloud/network/rules/PortForwardingRuleVO.java +++ b/server/src/com/cloud/network/rules/PortForwardingRuleVO.java @@ -18,6 +18,8 @@ package com.cloud.network.rules; +import java.util.List; + import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; @@ -25,6 +27,7 @@ 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; @@ -45,23 +48,39 @@ public class PortForwardingRuleVO extends FirewallRuleVO implements PortForwardi private int destinationPortEnd; @Column(name="instance_id") - private long virtualMachineId; + 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 sourceCidrs; + + + public void setSourceCidrList(List sourceCidrs) { + this.sourceCidrs=sourceCidrs; + } + + @Override + public List getSourceCidrList() { + return sourceCidrs; + } + + public PortForwardingRuleVO() { } - public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, long networkId, long accountId, long domainId, long instanceId) { + public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, List sourceCidrs, long networkId, long accountId, long domainId, long instanceId) { super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding); this.destinationIpAddress = dstIp; this.virtualMachineId = instanceId; this.destinationPortStart = dstPortStart; - this.destinationPortEnd = dstPortEnd; + this.destinationPortEnd = dstPortEnd; + this.sourceCidrs = sourceCidrs; } - public PortForwardingRuleVO(String xId, long srcIpId, int srcPort, Ip dstIp, int dstPort, String protocol, long networkId, long accountId, long domainId, long instanceId) { - this(xId, srcIpId, srcPort, srcPort, dstIp, dstPort, dstPort, protocol.toLowerCase(), networkId, accountId, domainId, instanceId); + public PortForwardingRuleVO(String xId, long srcIpId, int srcPort, Ip dstIp, int dstPort, String protocol, List sourceCidrs, long networkId, long accountId, long domainId, long instanceId) { + this(xId, srcIpId, srcPort, srcPort, dstIp, dstPort, dstPort, protocol.toLowerCase(), sourceCidrs, networkId, accountId, domainId, instanceId); } @Override diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 75cb73ea8ce..32679db4466 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -255,7 +255,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } PortForwardingRuleVO newRule = new PortForwardingRuleVO(rule.getXid(), rule.getSourceIpAddressId(), rule.getSourcePortStart(), rule.getSourcePortEnd(), dstIp, rule.getDestinationPortStart(), - rule.getDestinationPortEnd(), rule.getProtocol().toLowerCase(), networkId, accountId, domainId, vmId); + rule.getDestinationPortEnd(), rule.getProtocol().toLowerCase(), rule.getSourceCidrList(), networkId, accountId, domainId, vmId); newRule = _forwardingDao.persist(newRule); try { @@ -332,8 +332,8 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { throw new InvalidParameterValueException("Start port can't be bigger than end port"); } - FirewallRuleVO newRule = new FirewallRuleVO(rule.getXid(), rule.getSourceIpAddressId(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol().toLowerCase(), networkId, - accountId, domainId, rule.getPurpose()); + FirewallRuleVO newRule = new FirewallRuleVO(rule.getXid(), rule.getSourceIpAddressId(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol().toLowerCase(), + networkId, accountId, domainId, rule.getPurpose()); newRule = _firewallDao.persist(newRule); try { diff --git a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java index c718c80c3a7..6e368334f65 100644 --- a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java +++ b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java @@ -21,22 +21,33 @@ import java.util.List; 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) public class PortForwardingRulesDaoImpl extends GenericDaoBase implements PortForwardingRulesDao { + private static final Logger s_logger = Logger.getLogger(PortForwardingRulesDaoImpl.class); protected final SearchBuilder AllFieldsSearch; protected final SearchBuilder ApplicationSearch; protected final SearchBuilder ActiveRulesSearch; protected final SearchBuilder AllRulesSearchByVM; protected final SearchBuilder ActiveRulesSearchByAccount; + + protected final FirewallRulesCidrsDaoImpl _portForwardingRulesCidrsDao = ComponentLocator.inject(FirewallRulesCidrsDaoImpl.class); protected PortForwardingRulesDaoImpl() { super(); @@ -143,4 +154,53 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase cidrlist = portForwardingRule.getSourceCidrList(); + if (cidrlist == null) { + return; + } + _portForwardingRulesCidrsDao.persist(portForwardingRule.getId(), cidrlist); + } + + + public void loadSourceCidrs(PortForwardingRuleVO portForwardingRule){ + List 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); + loadSourceCidrs(dbfirewallRule); + + 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; + } + } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 4539cc61553..ee4a61b4446 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -85,6 +85,7 @@ DROP TABLE IF EXISTS `cloud`.`load_balancing_ip_map`; DROP TABLE IF EXISTS `cloud`.`load_balancing_rules`; DROP TABLE IF EXISTS `cloud`.`port_forwarding_rules`; DROP TABLE IF EXISTS `cloud`.`firewall_rules`; +DROP TABLE IF EXISTS `cloud`.`firewall_rules_cidrs`; DROP TABLE IF EXISTS `cloud`.`ssh_keypairs`; DROP TABLE IF EXISTS `cloud`.`usage_event`; DROP TABLE IF EXISTS `cloud`.`host_tags`; @@ -565,6 +566,15 @@ CREATE TABLE `cloud`.`firewall_rules` ( CONSTRAINT `fk_firewall_rules__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`firewall_rules_cidrs` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `firewall_rule_id` bigint(20) unsigned NOT NULL COMMENT 'firewall rule id', + `source_cidr` varchar(18) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fk_firewall_cidrs_firewall_rules` (`firewall_rule_id`), + CONSTRAINT `fk_firewall_cidrs_firewall_rules` FOREIGN KEY (`firewall_rule_id`) REFERENCES `firewall_rules` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 + CREATE TABLE `cloud`.`load_balancing_rules` ( `id` bigint unsigned NOT NULL, `name` varchar(255) NOT NULL,