You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ek...@apache.org on 2015/09/08 13:46:42 UTC
[1/3] git commit: updated refs/heads/master to 237e0e4
Repository: cloudstack
Updated Branches:
refs/heads/master 30792532e -> 237e0e461
CLOUDSTACK-8688 - default policies for INPUT and FORWARD should be set to DROP instead of ACCEPT
- In order to be able to access the routers via the link local interface, we have to add a rules with NEW and ESTABLISHED state
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/f5e5f4d0
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f5e5f4d0
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f5e5f4d0
Branch: refs/heads/master
Commit: f5e5f4d0026f8ffd6f3aa7e8e4c7be0cd809d6c9
Parents: 8221ebd
Author: wilderrodrigues <wr...@schubergphilis.com>
Authored: Thu Aug 27 15:21:30 2015 +0200
Committer: wilderrodrigues <wr...@schubergphilis.com>
Committed: Mon Aug 31 12:43:04 2015 +0200
----------------------------------------------------------------------
.../debian/config/etc/iptables/iptables-router | 2 +-
.../config/etc/iptables/iptables-vpcrouter | 2 +-
.../debian/config/opt/cloud/bin/configure.py | 4 +--
.../debian/config/opt/cloud/bin/cs/CsAddress.py | 30 ++++++++++++++++----
4 files changed, 28 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f5e5f4d0/systemvm/patches/debian/config/etc/iptables/iptables-router
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/etc/iptables/iptables-router b/systemvm/patches/debian/config/etc/iptables/iptables-router
index 0f82d20..b49b6b2 100644
--- a/systemvm/patches/debian/config/etc/iptables/iptables-router
+++ b/systemvm/patches/debian/config/etc/iptables/iptables-router
@@ -36,7 +36,7 @@ COMMIT
-A INPUT -i eth0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT
--A INPUT -i eth1 -p tcp -m tcp -m state --state NEW --dport 3922 -j ACCEPT
+-A INPUT -i eth1 -p tcp -m tcp -m state --state NEW,ESTABLISHED --dport 3922 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp -m state --state NEW --dport 80 -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth2 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f5e5f4d0/systemvm/patches/debian/config/etc/iptables/iptables-vpcrouter
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/etc/iptables/iptables-vpcrouter b/systemvm/patches/debian/config/etc/iptables/iptables-vpcrouter
index 18a3510..1c40493 100644
--- a/systemvm/patches/debian/config/etc/iptables/iptables-vpcrouter
+++ b/systemvm/patches/debian/config/etc/iptables/iptables-vpcrouter
@@ -28,7 +28,7 @@ COMMIT
-A INPUT -d 225.0.0.50/32 -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
--A INPUT -i eth0 -p tcp -m tcp -m state --state NEW --dport 3922 -j ACCEPT
+-A INPUT -i eth0 -p tcp -m tcp -m state --state NEW,ESTABLISHED --dport 3922 -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
COMMIT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f5e5f4d0/systemvm/patches/debian/config/opt/cloud/bin/configure.py
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/configure.py b/systemvm/patches/debian/config/opt/cloud/bin/configure.py
index a591737..c25f892 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/configure.py
+++ b/systemvm/patches/debian/config/opt/cloud/bin/configure.py
@@ -585,7 +585,7 @@ class CsForwardingRules(CsDataBag):
rule['protocol'],
self.portsToString(rule['public_ports'], ':'),
)
- fw7 = "-A FORWARD -i %s -o %s -p %s -m %s --dport %s -m state --state NEW -j ACCEPT" % \
+ fw7 = "-A FORWARD -i %s -o %s -p %s -m %s --dport %s -m state --state NEW,ESTABLISHED -j ACCEPT" % \
(
self.getDeviceByIp(rule['public_ip']),
self.getDeviceByIp(rule['internal_ip']),
@@ -599,7 +599,7 @@ class CsForwardingRules(CsDataBag):
self.fw.append(["nat", "", fw4])
self.fw.append(["nat", "", fw5])
self.fw.append(["nat", "", fw6])
- self.fw.append(["", "", fw7])
+ self.fw.append(["filter", "", fw7])
def forward_vpc(self, rule):
fw_prerout_rule = "-A PREROUTING -d %s/32 -i %s" % (rule["public_ip"], self.getDeviceByIp(rule['public_ip']))
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f5e5f4d0/systemvm/patches/debian/config/opt/cloud/bin/cs/CsAddress.py
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/cs/CsAddress.py b/systemvm/patches/debian/config/opt/cloud/bin/cs/CsAddress.py
index d49c47a..767e748 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/cs/CsAddress.py
+++ b/systemvm/patches/debian/config/opt/cloud/bin/cs/CsAddress.py
@@ -299,6 +299,10 @@ class CsIP:
CsRpsrfs(self.dev).enable()
self.post_config_change("add")
+ '''For isolated/redundant and dhcpsrvr routers, call this method after the post_config is complete '''
+ if not self.config.is_vpc():
+ self.setup_router_control()
+
def check_is_up(self):
""" Ensure device is up """
cmd = "ip link show %s | grep 'state DOWN'" % self.getDevice()
@@ -336,6 +340,19 @@ class CsIP:
return self.address['public_ip']
return "unknown"
+ def setup_router_control(self):
+ if self.config.is_vpc():
+ return
+
+ self.fw.append(
+ ["filter", "", "-A FW_OUTBOUND -m state --state RELATED,ESTABLISHED -j ACCEPT"])
+ self.fw.append(
+ ["filter", "", "-A INPUT -i eth1 -p tcp -m tcp --dport 3922 -m state --state NEW,ESTABLISHED -j ACCEPT"])
+
+ self.fw.append(["filter", "", "-P INPUT DROP"])
+ self.fw.append(["filter", "", "-P FORWARD DROP"])
+
+
def fw_router(self):
if self.config.is_vpc():
return
@@ -402,11 +419,6 @@ class CsIP:
"-A PREROUTING -i %s -m state --state NEW " % self.dev +
"-j CONNMARK --set-xmark %s/0xffffffff" % self.dnum])
- if self.get_type() in ["control"]:
- self.fw.append(
- ["filter", "", "-A FW_OUTBOUND -m state --state RELATED,ESTABLISHED -j ACCEPT"])
- self.fw.append(
- ["filter", "", "-A INPUT -i %s -p tcp -m tcp --dport 3922 -m state --state NEW -j ACCEPT" % self.dev])
self.fw.append(['', 'front', '-A FORWARD -j NETWORK_STATS'])
self.fw.append(['', 'front', '-A INPUT -j NETWORK_STATS'])
self.fw.append(['', 'front', '-A OUTPUT -j NETWORK_STATS'])
@@ -414,7 +426,7 @@ class CsIP:
self.fw.append(['', '', '-A NETWORK_STATS -i eth2 -o eth0'])
self.fw.append(['', '', '-A NETWORK_STATS -o eth2 ! -i eth0 -p tcp'])
self.fw.append(['', '', '-A NETWORK_STATS -i eth2 ! -o eth0 -p tcp'])
-
+
def fw_vpcrouter(self):
if not self.config.is_vpc():
return
@@ -480,6 +492,11 @@ class CsIP:
self.fw.append(["", "", "-A NETWORK_STATS -i eth2 -o eth0 -p tcp"])
self.fw.append(["", "", "-A NETWORK_STATS ! -i eth0 -o eth2 -p tcp"])
self.fw.append(["", "", "-A NETWORK_STATS -i eth2 ! -o eth0 -p tcp"])
+
+ self.fw.append(["filter", "", "-A INPUT -i eth0 -p tcp -m tcp --dport 3922 -m state --state NEW,ESTABLISHED -j ACCEPT"])
+
+ self.fw.append(["filter", "", "-P INPUT DROP"])
+ self.fw.append(["filter", "", "-P FORWARD DROP"])
def post_config_change(self, method):
route = CsRoute()
@@ -491,6 +508,7 @@ class CsIP:
self.fw_router()
self.fw_vpcrouter()
+
# On deletion nw_type will no longer be known
if self.get_type() in ["guest"] and self.config.is_vpc():
[2/3] git commit: updated refs/heads/master to 237e0e4
Posted by ek...@apache.org.
CLOUDSTACK-8688 - Adding Marvin tests in order to cover the fixes applied
- Changing refactored the utils.get_process_status() function
- Adding 2 tests: test_01_single_VPC_iptables_policies and test_02_routervm_iptables_policies
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/1742b10f
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1742b10f
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1742b10f
Branch: refs/heads/master
Commit: 1742b10f1b2f0c04df6dff504cdd90bb6e7b2bc3
Parents: f5e5f4d
Author: wilderrodrigues <wr...@schubergphilis.com>
Authored: Fri Sep 4 09:27:20 2015 +0200
Committer: wilderrodrigues <wr...@schubergphilis.com>
Committed: Mon Sep 7 17:00:32 2015 +0200
----------------------------------------------------------------------
.../test_routers_iptables_default_policy.py | 649 +++++++++++++++++++
tools/marvin/marvin/lib/utils.py | 75 ++-
2 files changed, 694 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1742b10f/test/integration/component/test_routers_iptables_default_policy.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_routers_iptables_default_policy.py b/test/integration/component/test_routers_iptables_default_policy.py
new file mode 100644
index 0000000..b72e45f
--- /dev/null
+++ b/test/integration/component/test_routers_iptables_default_policy.py
@@ -0,0 +1,649 @@
+# 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.
+
+""" Test VPC nics after router is destroyed """
+
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.base import (stopRouter,
+ startRouter,
+ destroyRouter,
+ Account,
+ VpcOffering,
+ VPC,
+ ServiceOffering,
+ NATRule,
+ NetworkACL,
+ PublicIPAddress,
+ NetworkOffering,
+ Network,
+ VirtualMachine,
+ LoadBalancerRule)
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template,
+ list_routers,
+ list_hosts)
+from marvin.lib.utils import (cleanup_resources,
+ get_process_status)
+import socket
+import time
+import inspect
+import logging
+
+
+class Services:
+ """Test VPC network services - Port Forwarding Rules Test Data Class.
+ """
+
+ def __init__(self):
+ self.services = {
+ "configurableData": {
+ "host": {
+ "password": "password",
+ "username": "root",
+ "port": 22
+ },
+ "input": "INPUT",
+ "forward": "FORWARD"
+ },
+ "account": {
+ "email": "test@test.com",
+ "firstname": "Test",
+ "lastname": "User",
+ "username": "test",
+ # Random characters are appended for unique
+ # username
+ "password": "password",
+ },
+ "service_offering": {
+ "name": "Tiny Instance",
+ "displaytext": "Tiny Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 128,
+ },
+ "shared_network_offering_sg": {
+ "name": "MySharedOffering-sg",
+ "displaytext": "MySharedOffering-sg",
+ "guestiptype": "Shared",
+ "supportedservices": "Dhcp,Dns,UserData,SecurityGroup",
+ "specifyVlan": "False",
+ "specifyIpRanges": "False",
+ "traffictype": "GUEST",
+ "serviceProviderList": {
+ "Dhcp": "VirtualRouter",
+ "Dns": "VirtualRouter",
+ "UserData": "VirtualRouter",
+ "SecurityGroup": "SecurityGroupProvider"
+ }
+ },
+ "network_offering": {
+ "name": 'Test Network offering',
+ "displaytext": 'Test Network offering',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ },
+ },
+ "vpc_network_offering": {
+ "name": 'VPC Network offering',
+ "displaytext": 'VPC Network off',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "useVpc": 'on',
+ "serviceProviderList": {
+ "Vpn": 'VpcVirtualRouter',
+ "Dhcp": 'VpcVirtualRouter',
+ "Dns": 'VpcVirtualRouter',
+ "SourceNat": 'VpcVirtualRouter',
+ "PortForwarding": 'VpcVirtualRouter',
+ "Lb": 'VpcVirtualRouter',
+ "UserData": 'VpcVirtualRouter',
+ "StaticNat": 'VpcVirtualRouter',
+ "NetworkACL": 'VpcVirtualRouter'
+ },
+ },
+ "vpc_network_offering_no_lb": {
+ "name": 'VPC Network offering',
+ "displaytext": 'VPC Network off',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "useVpc": 'on',
+ "serviceProviderList": {
+ "Dhcp": 'VpcVirtualRouter',
+ "Dns": 'VpcVirtualRouter',
+ "SourceNat": 'VpcVirtualRouter',
+ "PortForwarding": 'VpcVirtualRouter',
+ "UserData": 'VpcVirtualRouter',
+ "StaticNat": 'VpcVirtualRouter',
+ "NetworkACL": 'VpcVirtualRouter'
+ },
+ },
+ "vpc_offering": {
+ "name": 'VPC off',
+ "displaytext": 'VPC off',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat',
+ },
+ "redundant_vpc_offering": {
+ "name": 'Redundant VPC off',
+ "displaytext": 'Redundant VPC off',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat',
+ "serviceProviderList": {
+ "Vpn": 'VpcVirtualRouter',
+ "Dhcp": 'VpcVirtualRouter',
+ "Dns": 'VpcVirtualRouter',
+ "SourceNat": 'VpcVirtualRouter',
+ "PortForwarding": 'VpcVirtualRouter',
+ "Lb": 'VpcVirtualRouter',
+ "UserData": 'VpcVirtualRouter',
+ "StaticNat": 'VpcVirtualRouter',
+ "NetworkACL": 'VpcVirtualRouter'
+ },
+ "serviceCapabilityList": {
+ "SourceNat": {
+ "RedundantRouter": 'true'
+ }
+ },
+ },
+ "vpc": {
+ "name": "TestVPC",
+ "displaytext": "TestVPC",
+ "cidr": '10.1.1.1/16'
+ },
+ "network": {
+ "name": "Test Network",
+ "displaytext": "Test Network",
+ "netmask": '255.255.255.0'
+ },
+ "natrule": {
+ "privateport": 22,
+ "publicport": 22,
+ "startport": 22,
+ "endport": 22,
+ "protocol": "TCP",
+ "cidrlist": '0.0.0.0/0',
+ },
+ "virtual_machine": {
+ "displayname": "Test VM",
+ "username": "root",
+ "password": "password",
+ "ssh_port": 22,
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": 'TCP',
+ },
+ "ostype": 'CentOS 5.3 (64-bit)',
+ "timeout": 10,
+ }
+
+
+class TestVPCIpTablesPolicies(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ # We want to fail quicker if it's failure
+ socket.setdefaulttimeout(60)
+
+ cls.testClient = super(TestVPCIpTablesPolicies, cls).getClsTestClient()
+ cls.apiclient = cls.testClient.getApiClient()
+
+ cls.services = Services().services
+ # Get Zone, Domain and templates
+ cls.domain = get_domain(cls.apiclient)
+ cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
+ cls.template = get_template(
+ cls.apiclient,
+ cls.zone.id,
+ cls.services["ostype"])
+
+ cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+ cls.services["virtual_machine"]["template"] = cls.template.id
+
+ cls.account = Account.create(
+ cls.apiclient,
+ cls.services["account"],
+ admin=True,
+ domainid=cls.domain.id)
+
+ cls._cleanup = [cls.account]
+
+ cls.service_offering = ServiceOffering.create(
+ cls.apiclient,
+ cls.services["service_offering"])
+
+ cls._cleanup.append(cls.service_offering)
+
+ cls.logger = logging.getLogger('TestVPCIpTablesPolicies')
+ cls.stream_handler = logging.StreamHandler()
+ cls.logger.setLevel(logging.DEBUG)
+ cls.logger.addHandler(cls.stream_handler)
+
+ cls.entity_manager = EntityManager(cls.apiclient, cls.services, cls.service_offering, cls.account, cls.zone, cls._cleanup, cls.logger)
+
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ cleanup_resources(cls.apiclient, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def setUp(self):
+ self.logger.debug("Creating a VPC offering.")
+ self.vpc_off = VpcOffering.create(
+ self.apiclient,
+ self.services["vpc_offering"])
+
+ self.logger.debug("Enabling the VPC offering created")
+ self.vpc_off.update(self.apiclient, state='Enabled')
+
+ self.logger.debug("Creating a VPC network in the account: %s" % self.account.name)
+
+ self.vpc = VPC.create(
+ self.apiclient,
+ self.services["vpc"],
+ vpcofferingid=self.vpc_off.id,
+ zoneid=self.zone.id,
+ account=self.account.name,
+ domainid=self.account.domainid)
+
+ return
+
+ @attr(tags=["advanced", "intervlan"], required_hardware="true")
+ def test_01_single_VPC_iptables_policies(self):
+ """ Test iptables default INPUT/FORWARD policies on VPC router """
+ self.logger.debug("Starting test_01_single_VPC_iptables_policies")
+
+ routers = self.entity_manager.query_routers()
+
+ self.assertEqual(
+ isinstance(routers, list), True,
+ "Check for list routers response return valid data")
+
+ self.entity_manager.create_network(self.services["vpc_network_offering"], self.vpc.id, "10.1.1.1")
+ self.entity_manager.create_network(self.services["vpc_network_offering_no_lb"], self.vpc.id, "10.1.2.1")
+
+ self.entity_manager.add_nat_rules(self.vpc.id)
+ self.entity_manager.do_vpc_test()
+
+ for router in routers:
+ if not router.isredundantrouter and router.vpcid:
+ hosts = list_hosts(
+ self.apiclient,
+ id=router.hostid)
+ self.assertEqual(
+ isinstance(hosts, list),
+ True,
+ "Check for list hosts response return valid data")
+
+ host = hosts[0]
+ host.user = self.services["configurableData"]["host"]["username"]
+ host.passwd = self.services["configurableData"]["host"]["password"]
+ host.port = self.services["configurableData"]["host"]["port"]
+ tables = [self.services["configurableData"]["input"], self.services["configurableData"]["forward"]]
+
+ for table in tables:
+ try:
+ result = get_process_status(
+ host.ipaddress,
+ host.port,
+ host.user,
+ host.passwd,
+ router.linklocalip,
+ 'iptables -L %s' % table)
+ except KeyError:
+ self.skipTest(
+ "Provide a marvin config file with host\
+ credentials to run %s" %
+ self._testMethodName)
+
+ self.logger.debug("iptables -L %s: %s" % (table, result))
+ res = str(result)
+
+ self.assertEqual(
+ res.count("DROP"),
+ 1,
+ "%s Default Policy should be DROP" % table)
+
+
+class TestRouterIpTablesPolicies(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ # We want to fail quicker if it's failure
+ socket.setdefaulttimeout(60)
+
+ cls.testClient = super(TestRouterIpTablesPolicies, cls).getClsTestClient()
+ cls.apiclient = cls.testClient.getApiClient()
+
+ cls.services = Services().services
+ # Get Zone, Domain and templates
+ cls.domain = get_domain(cls.apiclient)
+ cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
+ cls.template = get_template(
+ cls.apiclient,
+ cls.zone.id,
+ cls.services["ostype"])
+
+ cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+ cls.services["virtual_machine"]["template"] = cls.template.id
+
+ cls.account = Account.create(
+ cls.apiclient,
+ cls.services["account"],
+ admin=True,
+ domainid=cls.domain.id)
+
+ cls._cleanup = [cls.account]
+
+ cls.service_offering = ServiceOffering.create(
+ cls.apiclient,
+ cls.services["service_offering"])
+
+ cls._cleanup.append(cls.service_offering)
+
+ cls.logger = logging.getLogger('TestRouterIpTablesPolicies')
+ cls.stream_handler = logging.StreamHandler()
+ cls.logger.setLevel(logging.DEBUG)
+ cls.logger.addHandler(cls.stream_handler)
+
+ cls.entity_manager = EntityManager(cls.apiclient, cls.services, cls.service_offering, cls.account, cls.zone, cls._cleanup, cls.logger)
+
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ cleanup_resources(cls.apiclient, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ @attr(tags=["advanced", "intervlan"], required_hardware="true")
+ def test_02_routervm_iptables_policies(self):
+ """ Test iptables default INPUT/FORWARD policy on RouterVM """
+
+ self.logger.debug("Starting test_02_routervm_iptables_policies")
+
+ vm1 = self.entity_manager.deployvm()
+
+ routers = self.entity_manager.query_routers()
+
+ self.assertEqual(
+ isinstance(routers, list), True,
+ "Check for list routers response return valid data")
+
+ for router in routers:
+ if not router.isredundantrouter and not router.vpcid:
+ hosts = list_hosts(
+ self.apiclient,
+ id=router.hostid)
+ self.assertEqual(
+ isinstance(hosts, list),
+ True,
+ "Check for list hosts response return valid data")
+
+ host = hosts[0]
+ host.user = self.services["configurableData"]["host"]["username"]
+ host.passwd = self.services["configurableData"]["host"]["password"]
+ host.port = self.services["configurableData"]["host"]["port"]
+ tables = [self.services["configurableData"]["input"], self.services["configurableData"]["forward"]]
+
+ for table in tables:
+ try:
+ result = get_process_status(
+ host.ipaddress,
+ host.port,
+ host.user,
+ host.passwd,
+ router.linklocalip,
+ 'iptables -L %s' % table)
+ except KeyError:
+ self.skipTest(
+ "Provide a marvin config file with host\
+ credentials to run %s" %
+ self._testMethodName)
+
+ self.logger.debug("iptables -L %s: %s" % (table, result))
+ res = str(result)
+
+ self.assertEqual(
+ res.count("DROP"),
+ 1,
+ "%s Default Policy should be DROP" % table)
+
+
+class EntityManager(object):
+
+ def __init__(self, apiclient, services, service_offering, account, zone, cleanup, logger):
+ self.apiclient = apiclient
+ self.services = services
+ self.service_offering = service_offering
+ self.account = account
+ self.zone = zone
+ self.cleanup = cleanup
+ self.logger = logger
+
+ self.networks = []
+ self.routers = []
+ self.ips = []
+
+ def add_nat_rules(self, vpc_id):
+ for o in self.networks:
+ for vm in o.get_vms():
+ if vm.get_ip() is None:
+ vm.set_ip(self.acquire_publicip(o.get_net(), vpc_id))
+ if vm.get_nat() is None:
+ vm.set_nat(self.create_natrule(vm.get_vm(), vm.get_ip(), o.get_net(), vpc_id))
+ time.sleep(5)
+
+ def do_vpc_test(self):
+ for o in self.networks:
+ for vm in o.get_vms():
+ self.check_ssh_into_vm(vm.get_vm(), vm.get_ip())
+
+ def create_natrule(self, vm, public_ip, network, vpc_id):
+ self.logger.debug("Creating NAT rule in network for vm with public IP")
+
+ nat_rule_services = self.services["natrule"]
+
+ nat_rule = NATRule.create(
+ self.apiclient,
+ vm,
+ nat_rule_services,
+ ipaddressid=public_ip.ipaddress.id,
+ openfirewall=False,
+ networkid=network.id,
+ vpcid=vpc_id)
+
+ self.logger.debug("Adding NetworkACL rules to make NAT rule accessible")
+ nwacl_nat = NetworkACL.create(
+ self.apiclient,
+ networkid=network.id,
+ services=nat_rule_services,
+ traffictype='Ingress'
+ )
+ self.logger.debug('nwacl_nat=%s' % nwacl_nat.__dict__)
+ return nat_rule
+
+ def check_ssh_into_vm(self, vm, public_ip):
+ self.logger.debug("Checking if we can SSH into VM=%s on public_ip=%s" %
+ (vm.name, public_ip.ipaddress.ipaddress))
+ vm.ssh_client = None
+ try:
+ vm.get_ssh_client(ipaddress=public_ip.ipaddress.ipaddress)
+ self.logger.debug("SSH into VM=%s on public_ip=%s is successful" %
+ (vm.name, public_ip.ipaddress.ipaddress))
+ except:
+ raise Exception("Failed to SSH into VM - %s" % (public_ip.ipaddress.ipaddress))
+
+ def create_network(self, net_offerring, vpc_id, gateway='10.1.1.1'):
+ try:
+ self.logger.debug('Create NetworkOffering')
+ net_offerring["name"] = "NET_OFF-" + str(gateway)
+ nw_off = NetworkOffering.create(
+ self.apiclient,
+ net_offerring,
+ conservemode=False)
+
+ nw_off.update(self.apiclient, state='Enabled')
+ self.cleanup.append(nw_off)
+ self.logger.debug('Created and Enabled NetworkOffering')
+
+ self.services["network"]["name"] = "NETWORK-" + str(gateway)
+ self.logger.debug('Adding Network=%s to VPC ID %s' % (self.services["network"], vpc_id))
+ obj_network = Network.create(
+ self.apiclient,
+ self.services["network"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkofferingid=nw_off.id,
+ zoneid=self.zone.id,
+ gateway=gateway,
+ vpcid=vpc_id)
+ self.logger.debug("Created network with ID: %s" % obj_network.id)
+ except Exception, e:
+ raise Exception('Unable to create a Network with offering=%s because of %s ' % (net_offerring, e))
+
+ o = networkO(obj_network)
+ o.add_vm(self.deployvm_in_network(obj_network))
+
+ self.networks.append(o)
+ return o
+
+ def deployvm_in_network(self, network):
+ try:
+ self.logger.debug('Creating VM in network=%s' % network.name)
+ vm = VirtualMachine.create(
+ self.apiclient,
+ self.services["virtual_machine"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ networkids=[str(network.id)])
+ self.logger.debug('Created VM=%s in network=%s' % (vm.id, network.name))
+ return vm
+ except:
+ raise Exception('Unable to create VM in a Network=%s' % network.name)
+
+ def deployvm(self):
+ try:
+ self.logger.debug('Creating VM')
+ vm = VirtualMachine.create(
+ self.apiclient,
+ self.services["virtual_machine"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id)
+ self.logger.debug('Created VM=%s' % vm.id)
+ return vm
+ except:
+ raise Exception('Unable to create VM')
+
+ def acquire_publicip(self, network, vpc_id):
+ self.logger.debug("Associating public IP for network: %s" % network.name)
+ public_ip = PublicIPAddress.create(
+ self.apiclient,
+ accountid=self.account.name,
+ zoneid=self.zone.id,
+ domainid=self.account.domainid,
+ networkid=network.id,
+ vpcid=vpc_id)
+ self.logger.debug("Associated %s with network %s" % (
+ public_ip.ipaddress.ipaddress,
+ network.id))
+
+ self.ips.append(public_ip)
+ return public_ip
+
+ def query_routers(self):
+ self.routers = list_routers(self.apiclient,
+ account=self.account.name,
+ domainid=self.account.domainid)
+
+ return self.routers
+
+ def stop_router(self):
+ self.logger.debug('Stopping router')
+ for router in self.routers:
+ cmd = stopRouter.stopRouterCmd()
+ cmd.id = router.id
+ self.apiclient.stopRouter(cmd)
+
+ def destroy_router(self):
+ self.logger.debug('Destroying router')
+ for router in self.routers:
+ cmd = destroyRouter.destroyRouterCmd()
+ cmd.id = router.id
+ self.apiclient.destroyRouter(cmd)
+
+ def start_router(self):
+ self.logger.debug('Starting router')
+ for router in self.routers:
+ cmd = startRouter.startRouterCmd()
+ cmd.id = router.id
+ self.apiclient.startRouter(cmd)
+
+
+class networkO(object):
+ def __init__(self, net):
+ self.network = net
+ self.vms = []
+
+ def get_net(self):
+ return self.network
+
+ def add_vm(self, vm):
+ self.vms.append(vmsO(vm))
+
+ def get_vms(self):
+ return self.vms
+
+
+class vmsO(object):
+ def __init__(self, vm):
+ self.vm = vm
+ self.ip = None
+ self.nat = None
+
+ def get_vm(self):
+ return self.vm
+
+ def get_ip(self):
+ return self.ip
+
+ def get_nat(self):
+ return self.nat
+
+ def set_ip(self, ip):
+ self.ip = ip
+
+ def set_nat(self, nat):
+ self.nat = nat
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1742b10f/tools/marvin/marvin/lib/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/utils.py b/tools/marvin/marvin/lib/utils.py
index 4faced5..97b80ac 100644
--- a/tools/marvin/marvin/lib/utils.py
+++ b/tools/marvin/marvin/lib/utils.py
@@ -41,6 +41,43 @@ from marvin.codes import (
EMPTY_LIST,
FAILED)
+def _configure_ssh_credentials(hypervisor):
+ ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+
+ if (str(hypervisor).lower() == 'vmware'
+ or str(hypervisor).lower() == 'hyperv'):
+ ssh_command = "ssh -i /var/cloudstack/management/.ssh/id_rsa -ostricthostkeychecking=no "
+
+ return ssh_command
+
+
+def _configure_timeout(hypervisor):
+ timeout = 5
+
+ # Increase hop into router
+ if str(hypervisor).lower() == 'hyperv':
+ timeout = 12
+
+ return timeout
+
+
+def _execute_ssh_command(hostip, port, username, password, ssh_command):
+ #SSH to the machine
+ ssh = SshClient(hostip, port, username, password)
+ # Ensure the SSH login is successful
+ while True:
+ res = ssh.execute(ssh_command)
+ if "Connection refused".lower() in res[0].lower():
+ pass
+ elif res[0] != "Host key verification failed.":
+ break
+ elif timeout == 0:
+ break
+
+ time.sleep(5)
+ timeout = timeout - 1
+ return res
+
def restart_mgmt_server(server):
"""Restarts the management server"""
@@ -191,40 +228,19 @@ def get_host_credentials(config, hostip):
raise KeyError("Please provide the marvin configuration file with credentials to your hosts")
-def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None):
- """Double hop and returns a process status"""
+def get_process_status(hostip, port, username, password, linklocalip, command, hypervisor=None):
+ """Double hop and returns a command execution result"""
- #SSH to the machine
- ssh = SshClient(hostip, port, username, password)
- if (str(hypervisor).lower() == 'vmware'
- or str(hypervisor).lower() == 'hyperv'):
- ssh_command = "ssh -i /var/cloudstack/management/.ssh/id_rsa -ostricthostkeychecking=no "
- else:
- ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+ ssh_command = _configure_ssh_credentials(hypervisor)
ssh_command = ssh_command +\
"-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % (
linklocalip,
- process)
+ command)
+ timeout = _configure_timeout(hypervisor)
- # Double hop into router
- if str(hypervisor).lower() == 'hyperv':
- timeout = 12
- else:
- timeout = 5
- # Ensure the SSH login is successful
- while True:
- res = ssh.execute(ssh_command)
- if "Connection refused".lower() in res[0].lower():
- pass
- elif res[0] != "Host key verification failed.":
- break
- elif timeout == 0:
- break
-
- time.sleep(5)
- timeout = timeout - 1
- return res
+ result = _execute_ssh_command(hostip, port, username, password, ssh_command)
+ return result
def isAlmostEqual(first_digit, second_digit, range=0):
@@ -504,5 +520,4 @@ def verifyRouterState(apiclient, routerid, allowedstates):
if routers[0].state.lower() not in allowedstates:
return [FAIL, "state of the router should be in %s but is %s" %
(allowedstates, routers[0].state)]
- return [PASS, None]
-
+ return [PASS, None]
\ No newline at end of file
[3/3] git commit: updated refs/heads/master to 237e0e4
Posted by ek...@apache.org.
Merge pull request #765 from schubergphilis/fix/default_policies
CLOUDSTACK-8688 - default policies for INPUT and FORWARD should be set to DROP instead of ACCEPT
- In order to be able to access the routers via the link local interface, we have to add a rules with NEW and ESTABLISHED state
* pr/765:
CLOUDSTACK-8688 - Adding Marvin tests in order to cover the fixes applied
CLOUDSTACK-8688 - default policies for INPUT and FORWARD should be set to DROP instead of ACCEPT
Signed-off-by: wilderrodrigues <wr...@schubergphilis.com>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/237e0e46
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/237e0e46
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/237e0e46
Branch: refs/heads/master
Commit: 237e0e4611dd3d0ae56a8c0557dba93e7fbd3440
Parents: 3079253 1742b10
Author: wilderrodrigues <wr...@schubergphilis.com>
Authored: Tue Sep 8 13:45:14 2015 +0200
Committer: wilderrodrigues <wr...@schubergphilis.com>
Committed: Tue Sep 8 13:45:19 2015 +0200
----------------------------------------------------------------------
.../debian/config/etc/iptables/iptables-router | 2 +-
.../config/etc/iptables/iptables-vpcrouter | 2 +-
.../debian/config/opt/cloud/bin/configure.py | 4 +-
.../debian/config/opt/cloud/bin/cs/CsAddress.py | 30 +-
.../test_routers_iptables_default_policy.py | 649 +++++++++++++++++++
tools/marvin/marvin/lib/utils.py | 75 ++-
6 files changed, 722 insertions(+), 40 deletions(-)
----------------------------------------------------------------------