Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 1 | # Copyright 2013 Red Hat, Inc. |
| 2 | # All Rights Reserved. |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 5 | # not use this file except in compliance with the License. You may obtain |
| 6 | # a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 13 | # License for the specific language governing permissions and limitations |
| 14 | # under the License. |
| 15 | |
Doug Hellmann | 583ce2c | 2015-03-11 14:55:46 +0000 | [diff] [blame] | 16 | from oslo_log import log as logging |
Matthew Treinish | 01472ff | 2015-02-20 17:26:52 -0500 | [diff] [blame] | 17 | |
Andrea Frittoli | f9cde7e | 2014-02-18 09:57:04 +0000 | [diff] [blame] | 18 | from tempest import clients |
Fei Long Wang | d39431f | 2015-05-14 11:30:48 +1200 | [diff] [blame] | 19 | from tempest.common.utils import data_utils |
Matthew Treinish | 6c07229 | 2014-01-29 19:15:52 +0000 | [diff] [blame] | 20 | from tempest import config |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 21 | from tempest.scenario import manager |
Masayuki Igawa | 4ded9f0 | 2014-02-17 15:05:59 +0900 | [diff] [blame] | 22 | from tempest import test |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 23 | |
Matthew Treinish | 6c07229 | 2014-01-29 19:15:52 +0000 | [diff] [blame] | 24 | CONF = config.CONF |
| 25 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 26 | LOG = logging.getLogger(__name__) |
| 27 | |
| 28 | |
Andrea Frittoli | 4971fc8 | 2014-09-25 10:22:20 +0100 | [diff] [blame] | 29 | class TestSecurityGroupsBasicOps(manager.NetworkScenarioTest): |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 30 | |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 31 | """The test suite for security groups |
| 32 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 33 | This test suite assumes that Nova has been configured to |
| 34 | boot VM's with Neutron-managed networking, and attempts to |
| 35 | verify cross tenant connectivity as follows |
| 36 | |
| 37 | ssh: |
| 38 | in order to overcome "ip namespace", each tenant has an "access point" |
| 39 | VM with floating-ip open to incoming ssh connection allowing network |
| 40 | commands (ping/ssh) to be executed from within the |
| 41 | tenant-network-namespace |
| 42 | Tempest host performs key-based authentication to the ssh server via |
| 43 | floating IP address |
| 44 | |
| 45 | connectivity test is done by pinging destination server via source server |
| 46 | ssh connection. |
| 47 | success - ping returns |
| 48 | failure - ping_timeout reached |
| 49 | |
| 50 | setup: |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 51 | for primary tenant: |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 52 | 1. create a network&subnet |
| 53 | 2. create a router (if public router isn't configured) |
| 54 | 3. connect tenant network to public network via router |
| 55 | 4. create an access point: |
| 56 | a. a security group open to incoming ssh connection |
| 57 | b. a VM with a floating ip |
| 58 | 5. create a general empty security group (same as "default", but |
| 59 | without rules allowing in-tenant traffic) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 60 | |
| 61 | tests: |
| 62 | 1. _verify_network_details |
| 63 | 2. _verify_mac_addr: for each access point verify that |
| 64 | (subnet, fix_ip, mac address) are as defined in the port list |
| 65 | 3. _test_in_tenant_block: test that in-tenant traffic is disabled |
| 66 | without rules allowing it |
| 67 | 4. _test_in_tenant_allow: test that in-tenant traffic is enabled |
| 68 | once an appropriate rule has been created |
| 69 | 5. _test_cross_tenant_block: test that cross-tenant traffic is disabled |
| 70 | without a rule allowing it on destination tenant |
| 71 | 6. _test_cross_tenant_allow: |
| 72 | * test that cross-tenant traffic is enabled once an appropriate |
| 73 | rule has been created on destination tenant. |
| 74 | * test that reverse traffic is still blocked |
Fei Long Wang | 50131ee | 2015-02-02 16:58:24 +1300 | [diff] [blame] | 75 | * test than reverse traffic is enabled once an appropriate rule has |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 76 | been created on source tenant |
Rajkumar Thiyagarajan | d9e964a | 2014-12-17 01:55:52 -0800 | [diff] [blame] | 77 | 7._test_port_update_new_security_group: |
| 78 | * test that traffic is blocked with default security group |
| 79 | * test that traffic is enabled after updating port with new security |
| 80 | group having appropriate rule |
prdsilva | 8b733ad | 2014-12-09 02:54:49 -0800 | [diff] [blame] | 81 | 8. _test_multiple_security_groups: test multiple security groups can be |
| 82 | associated with the vm |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 83 | |
| 84 | assumptions: |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 85 | 1. alt_tenant/user existed and is different from primary_tenant/user |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 86 | 2. Public network is defined and reachable from the Tempest host |
| 87 | 3. Public router can either be: |
| 88 | * defined, in which case all tenants networks can connect directly |
| 89 | to it, and cross tenant check will be done on the private IP of the |
| 90 | destination tenant |
| 91 | or |
Fei Long Wang | 50131ee | 2015-02-02 16:58:24 +1300 | [diff] [blame] | 92 | * not defined (empty string), in which case each tenant will have |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 93 | its own router connected to the public network |
| 94 | """ |
| 95 | |
Andrea Frittoli | b21de6c | 2015-02-06 20:12:38 +0000 | [diff] [blame] | 96 | credentials = ['primary', 'alt', 'admin'] |
| 97 | |
Joe Gordon | 28788b4 | 2015-02-25 12:42:37 -0800 | [diff] [blame] | 98 | class TenantProperties(object): |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 99 | """helper class to save tenant details |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 100 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 101 | id |
| 102 | credentials |
| 103 | network |
| 104 | subnet |
| 105 | security groups |
| 106 | servers |
| 107 | access point |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 108 | """ |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 109 | |
Andrea Frittoli | 422fbdf | 2014-03-20 10:05:18 +0000 | [diff] [blame] | 110 | def __init__(self, credentials): |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 111 | self.manager = clients.Manager(credentials) |
Andrea Frittoli | 422fbdf | 2014-03-20 10:05:18 +0000 | [diff] [blame] | 112 | # Credentials from manager are filled with both names and IDs |
| 113 | self.creds = self.manager.credentials |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 114 | self.network = None |
| 115 | self.subnet = None |
| 116 | self.router = None |
| 117 | self.security_groups = {} |
| 118 | self.servers = list() |
| 119 | |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 120 | def set_network(self, network, subnet, router): |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 121 | self.network = network |
| 122 | self.subnet = subnet |
| 123 | self.router = router |
| 124 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 125 | @classmethod |
Emily Hugenbruch | 5e2d2a2 | 2015-02-25 21:35:45 +0000 | [diff] [blame] | 126 | def skip_checks(cls): |
| 127 | super(TestSecurityGroupsBasicOps, cls).skip_checks() |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 128 | if CONF.baremetal.driver_enabled: |
| 129 | msg = ('Not currently supported by baremetal.') |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 130 | raise cls.skipException(msg) |
Itzik Brown | 0695267 | 2015-03-29 12:38:58 +0300 | [diff] [blame] | 131 | if CONF.network.port_vnic_type in ['direct', 'macvtap']: |
| 132 | msg = ('Not currently supported when using vnic_type' |
| 133 | ' direct or macvtap') |
| 134 | raise cls.skipException(msg) |
Matthew Treinish | 6c07229 | 2014-01-29 19:15:52 +0000 | [diff] [blame] | 135 | if not (CONF.network.tenant_networks_reachable or |
| 136 | CONF.network.public_network_id): |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 137 | msg = ('Either tenant_networks_reachable must be "true", or ' |
| 138 | 'public_network_id must be defined.') |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 139 | raise cls.skipException(msg) |
| 140 | |
| 141 | @classmethod |
Emily Hugenbruch | 5e2d2a2 | 2015-02-25 21:35:45 +0000 | [diff] [blame] | 142 | def setup_credentials(cls): |
Yair Fried | 764610a | 2014-04-07 12:17:05 +0300 | [diff] [blame] | 143 | # Create no network resources for these tests. |
| 144 | cls.set_network_resources() |
Emily Hugenbruch | 5e2d2a2 | 2015-02-25 21:35:45 +0000 | [diff] [blame] | 145 | super(TestSecurityGroupsBasicOps, cls).setup_credentials() |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 146 | # TODO(mnewby) Consider looking up entities as needed instead |
| 147 | # of storing them as collections on the class. |
Yair Fried | 79b0a91 | 2014-10-20 11:15:37 +0300 | [diff] [blame] | 148 | |
Yair Fried | 79b0a91 | 2014-10-20 11:15:37 +0300 | [diff] [blame] | 149 | # Credentials from the manager are filled with both IDs and Names |
| 150 | cls.alt_creds = cls.alt_manager.credentials |
| 151 | |
Emily Hugenbruch | 5e2d2a2 | 2015-02-25 21:35:45 +0000 | [diff] [blame] | 152 | @classmethod |
| 153 | def resource_setup(cls): |
| 154 | super(TestSecurityGroupsBasicOps, cls).resource_setup() |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 155 | cls.floating_ips = {} |
| 156 | cls.tenants = {} |
Andrea Frittoli | b21de6c | 2015-02-06 20:12:38 +0000 | [diff] [blame] | 157 | creds = cls.manager.credentials |
Andrea Frittoli | 422fbdf | 2014-03-20 10:05:18 +0000 | [diff] [blame] | 158 | cls.primary_tenant = cls.TenantProperties(creds) |
| 159 | cls.alt_tenant = cls.TenantProperties(cls.alt_creds) |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 160 | for tenant in [cls.primary_tenant, cls.alt_tenant]: |
Andrea Frittoli | 86ad28d | 2014-03-20 10:09:12 +0000 | [diff] [blame] | 161 | cls.tenants[tenant.creds.tenant_id] = tenant |
Emily Hugenbruch | 5e2d2a2 | 2015-02-25 21:35:45 +0000 | [diff] [blame] | 162 | |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 163 | cls.floating_ip_access = not CONF.network.public_router_id |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 164 | |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 165 | def setUp(self): |
| 166 | super(TestSecurityGroupsBasicOps, self).setUp() |
| 167 | self._deploy_tenant(self.primary_tenant) |
| 168 | self._verify_network_details(self.primary_tenant) |
| 169 | self._verify_mac_addr(self.primary_tenant) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 170 | |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 171 | def _create_tenant_keypairs(self, tenant): |
| 172 | keypair = self.create_keypair(tenant.manager.keypairs_client) |
| 173 | tenant.keypair = keypair |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 174 | |
| 175 | def _create_tenant_security_groups(self, tenant): |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 176 | access_sg = self._create_empty_security_group( |
| 177 | namestart='secgroup_access-', |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 178 | tenant_id=tenant.creds.tenant_id, |
| 179 | client=tenant.manager.network_client |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 180 | ) |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 181 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 182 | # don't use default secgroup since it allows in-tenant traffic |
| 183 | def_sg = self._create_empty_security_group( |
| 184 | namestart='secgroup_general-', |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 185 | tenant_id=tenant.creds.tenant_id, |
| 186 | client=tenant.manager.network_client |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 187 | ) |
| 188 | tenant.security_groups.update(access=access_sg, default=def_sg) |
| 189 | ssh_rule = dict( |
| 190 | protocol='tcp', |
| 191 | port_range_min=22, |
| 192 | port_range_max=22, |
| 193 | direction='ingress', |
| 194 | ) |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 195 | self._create_security_group_rule(secgroup=access_sg, |
| 196 | client=tenant.manager.network_client, |
| 197 | **ssh_rule) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 198 | |
| 199 | def _verify_network_details(self, tenant): |
| 200 | # Checks that we see the newly created network/subnet/router via |
| 201 | # checking the result of list_[networks,routers,subnets] |
| 202 | # Check that (router, subnet) couple exist in port_list |
| 203 | seen_nets = self._list_networks() |
| 204 | seen_names = [n['name'] for n in seen_nets] |
| 205 | seen_ids = [n['id'] for n in seen_nets] |
| 206 | |
| 207 | self.assertIn(tenant.network.name, seen_names) |
| 208 | self.assertIn(tenant.network.id, seen_ids) |
| 209 | |
| 210 | seen_subnets = [(n['id'], n['cidr'], n['network_id']) |
| 211 | for n in self._list_subnets()] |
| 212 | mysubnet = (tenant.subnet.id, tenant.subnet.cidr, tenant.network.id) |
| 213 | self.assertIn(mysubnet, seen_subnets) |
| 214 | |
| 215 | seen_routers = self._list_routers() |
| 216 | seen_router_ids = [n['id'] for n in seen_routers] |
| 217 | seen_router_names = [n['name'] for n in seen_routers] |
| 218 | |
| 219 | self.assertIn(tenant.router.name, seen_router_names) |
| 220 | self.assertIn(tenant.router.id, seen_router_ids) |
| 221 | |
| 222 | myport = (tenant.router.id, tenant.subnet.id) |
| 223 | router_ports = [(i['device_id'], i['fixed_ips'][0]['subnet_id']) for i |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 224 | in self._list_ports() |
armando-migliaccio | bcfbbeb | 2014-08-11 18:33:47 -0700 | [diff] [blame] | 225 | if self._is_router_port(i)] |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 226 | |
| 227 | self.assertIn(myport, router_ports) |
| 228 | |
armando-migliaccio | bcfbbeb | 2014-08-11 18:33:47 -0700 | [diff] [blame] | 229 | def _is_router_port(self, port): |
| 230 | """Return True if port is a router interface.""" |
| 231 | # NOTE(armando-migliaccio): match device owner for both centralized |
| 232 | # and distributed routers; 'device_owner' is "" by default. |
| 233 | return port['device_owner'].startswith('network:router_interface') |
| 234 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 235 | def _create_server(self, name, tenant, security_groups=None): |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 236 | """creates a server and assigns to security group""" |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 237 | if security_groups is None: |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 238 | security_groups = [tenant.security_groups['default']] |
Ken'ichi Ohmichi | 1b3461e | 2014-12-02 03:41:07 +0000 | [diff] [blame] | 239 | security_groups_names = [{'name': s['name']} for s in security_groups] |
Ken'ichi Ohmichi | f2d436e | 2015-09-03 01:13:16 +0000 | [diff] [blame] | 240 | server = self.create_server( |
| 241 | name=name, |
lanoux | 5fc1452 | 2015-09-21 08:17:35 +0000 | [diff] [blame] | 242 | networks=[{'uuid': tenant.network.id}], |
| 243 | key_name=tenant.keypair['name'], |
| 244 | security_groups=security_groups_names, |
| 245 | wait_until='ACTIVE', |
| 246 | clients=tenant.manager) |
Claudiu Belu | faa9891 | 2014-09-01 16:50:28 +0300 | [diff] [blame] | 247 | self.assertEqual( |
| 248 | sorted([s['name'] for s in security_groups]), |
| 249 | sorted([s['name'] for s in server['security_groups']])) |
| 250 | return server |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 251 | |
| 252 | def _create_tenant_servers(self, tenant, num=1): |
| 253 | for i in range(num): |
Ken'ichi Ohmichi | 6ded8df | 2015-03-23 02:00:19 +0000 | [diff] [blame] | 254 | name = 'server-{tenant}-gen-{num}'.format( |
Andrea Frittoli | 86ad28d | 2014-03-20 10:09:12 +0000 | [diff] [blame] | 255 | tenant=tenant.creds.tenant_name, |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 256 | num=i |
| 257 | ) |
| 258 | name = data_utils.rand_name(name) |
| 259 | server = self._create_server(name, tenant) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 260 | tenant.servers.append(server) |
| 261 | |
| 262 | def _set_access_point(self, tenant): |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 263 | # creates a server in a secgroup with rule allowing external ssh |
| 264 | # in order to access tenant internal network |
| 265 | # workaround ip namespace |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 266 | secgroups = tenant.security_groups.values() |
Ken'ichi Ohmichi | 6ded8df | 2015-03-23 02:00:19 +0000 | [diff] [blame] | 267 | name = 'server-{tenant}-access_point'.format( |
Andrea Frittoli | 86ad28d | 2014-03-20 10:09:12 +0000 | [diff] [blame] | 268 | tenant=tenant.creds.tenant_name) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 269 | name = data_utils.rand_name(name) |
| 270 | server = self._create_server(name, tenant, |
| 271 | security_groups=secgroups) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 272 | tenant.access_point = server |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 273 | self._assign_floating_ips(tenant, server) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 274 | |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 275 | def _assign_floating_ips(self, tenant, server): |
Matthew Treinish | 6c07229 | 2014-01-29 19:15:52 +0000 | [diff] [blame] | 276 | public_network_id = CONF.network.public_network_id |
Yair Fried | ae0e73d | 2014-11-24 11:56:26 +0200 | [diff] [blame] | 277 | floating_ip = self.create_floating_ip( |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 278 | server, public_network_id, |
John Warren | fbf2a89 | 2015-11-17 12:36:14 -0500 | [diff] [blame] | 279 | client=tenant.manager.floating_ips_client) |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 280 | self.floating_ips.setdefault(server['id'], floating_ip) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 281 | |
| 282 | def _create_tenant_network(self, tenant): |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 283 | network, subnet, router = self.create_networks( |
John Warren | 94d8faf | 2015-09-15 12:22:24 -0400 | [diff] [blame] | 284 | client=tenant.manager.network_client, |
John Warren | 3961acd | 2015-10-02 14:38:53 -0400 | [diff] [blame] | 285 | networks_client=tenant.manager.networks_client, |
| 286 | subnets_client=tenant.manager.subnets_client) |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 287 | tenant.set_network(network, subnet, router) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 288 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 289 | def _deploy_tenant(self, tenant_or_id): |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 290 | """creates: |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 291 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 292 | network |
| 293 | subnet |
| 294 | router (if public not defined) |
| 295 | access security group |
| 296 | access-point server |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 297 | """ |
| 298 | if not isinstance(tenant_or_id, self.TenantProperties): |
| 299 | tenant = self.tenants[tenant_or_id] |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 300 | else: |
| 301 | tenant = tenant_or_id |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 302 | self._create_tenant_keypairs(tenant) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 303 | self._create_tenant_network(tenant) |
| 304 | self._create_tenant_security_groups(tenant) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 305 | self._set_access_point(tenant) |
| 306 | |
| 307 | def _get_server_ip(self, server, floating=False): |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 308 | """returns the ip (floating/internal) of a server""" |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 309 | if floating: |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 310 | server_ip = self.floating_ips[server['id']].floating_ip_address |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 311 | else: |
armando-migliaccio | d03f264 | 2014-02-21 19:55:50 -0800 | [diff] [blame] | 312 | server_ip = None |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 313 | network_name = self.tenants[server['tenant_id']].network.name |
| 314 | if network_name in server['addresses']: |
| 315 | server_ip = server['addresses'][network_name][0]['addr'] |
armando-migliaccio | d03f264 | 2014-02-21 19:55:50 -0800 | [diff] [blame] | 316 | return server_ip |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 317 | |
| 318 | def _connect_to_access_point(self, tenant): |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 319 | """create ssh connection to tenant access point""" |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 320 | access_point_ssh = \ |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 321 | self.floating_ips[tenant.access_point['id']].floating_ip_address |
| 322 | private_key = tenant.keypair['private_key'] |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 323 | access_point_ssh = self._ssh_to_server(access_point_ssh, |
| 324 | private_key=private_key) |
| 325 | return access_point_ssh |
| 326 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 327 | def _check_connectivity(self, access_point, ip, should_succeed=True): |
| 328 | if should_succeed: |
| 329 | msg = "Timed out waiting for %s to become reachable" % ip |
| 330 | else: |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 331 | msg = "%s is reachable" % ip |
Matthew Treinish | 5348313 | 2014-12-09 18:50:06 -0500 | [diff] [blame] | 332 | self.assertTrue(self._check_remote_connectivity(access_point, ip, |
| 333 | should_succeed), msg) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 334 | |
| 335 | def _test_in_tenant_block(self, tenant): |
| 336 | access_point_ssh = self._connect_to_access_point(tenant) |
| 337 | for server in tenant.servers: |
| 338 | self._check_connectivity(access_point=access_point_ssh, |
| 339 | ip=self._get_server_ip(server), |
| 340 | should_succeed=False) |
| 341 | |
| 342 | def _test_in_tenant_allow(self, tenant): |
| 343 | ruleset = dict( |
| 344 | protocol='icmp', |
| 345 | remote_group_id=tenant.security_groups['default'].id, |
| 346 | direction='ingress' |
| 347 | ) |
Matthew Treinish | b7144eb | 2013-12-13 22:57:35 +0000 | [diff] [blame] | 348 | self._create_security_group_rule( |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 349 | secgroup=tenant.security_groups['default'], |
| 350 | **ruleset |
| 351 | ) |
| 352 | access_point_ssh = self._connect_to_access_point(tenant) |
| 353 | for server in tenant.servers: |
| 354 | self._check_connectivity(access_point=access_point_ssh, |
| 355 | ip=self._get_server_ip(server)) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 356 | |
| 357 | def _test_cross_tenant_block(self, source_tenant, dest_tenant): |
Ken'ichi Ohmichi | c4e4f1c | 2015-11-17 08:16:12 +0000 | [diff] [blame] | 358 | # if public router isn't defined, then dest_tenant access is via |
| 359 | # floating-ip |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 360 | access_point_ssh = self._connect_to_access_point(source_tenant) |
| 361 | ip = self._get_server_ip(dest_tenant.access_point, |
| 362 | floating=self.floating_ip_access) |
| 363 | self._check_connectivity(access_point=access_point_ssh, ip=ip, |
| 364 | should_succeed=False) |
| 365 | |
| 366 | def _test_cross_tenant_allow(self, source_tenant, dest_tenant): |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 367 | """check for each direction: |
| 368 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 369 | creating rule for tenant incoming traffic enables only 1way traffic |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 370 | """ |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 371 | ruleset = dict( |
| 372 | protocol='icmp', |
| 373 | direction='ingress' |
| 374 | ) |
Matthew Treinish | b7144eb | 2013-12-13 22:57:35 +0000 | [diff] [blame] | 375 | self._create_security_group_rule( |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 376 | secgroup=dest_tenant.security_groups['default'], |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 377 | client=dest_tenant.manager.network_client, |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 378 | **ruleset |
| 379 | ) |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 380 | access_point_ssh = self._connect_to_access_point(source_tenant) |
| 381 | ip = self._get_server_ip(dest_tenant.access_point, |
| 382 | floating=self.floating_ip_access) |
| 383 | self._check_connectivity(access_point_ssh, ip) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 384 | |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 385 | # test that reverse traffic is still blocked |
| 386 | self._test_cross_tenant_block(dest_tenant, source_tenant) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 387 | |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 388 | # allow reverse traffic and check |
Matthew Treinish | b7144eb | 2013-12-13 22:57:35 +0000 | [diff] [blame] | 389 | self._create_security_group_rule( |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 390 | secgroup=source_tenant.security_groups['default'], |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 391 | client=source_tenant.manager.network_client, |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 392 | **ruleset |
| 393 | ) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 394 | |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 395 | access_point_ssh_2 = self._connect_to_access_point(dest_tenant) |
| 396 | ip = self._get_server_ip(source_tenant.access_point, |
| 397 | floating=self.floating_ip_access) |
| 398 | self._check_connectivity(access_point_ssh_2, ip) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 399 | |
| 400 | def _verify_mac_addr(self, tenant): |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 401 | """Verify that VM has the same ip, mac as listed in port""" |
| 402 | |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 403 | access_point_ssh = self._connect_to_access_point(tenant) |
| 404 | mac_addr = access_point_ssh.get_mac_address() |
| 405 | mac_addr = mac_addr.strip().lower() |
Henry Gessau | 78ab4b0 | 2014-03-31 15:10:13 -0400 | [diff] [blame] | 406 | # Get the fixed_ips and mac_address fields of all ports. Select |
| 407 | # only those two columns to reduce the size of the response. |
Yair Fried | db6c9e9 | 2014-08-06 08:53:13 +0300 | [diff] [blame] | 408 | port_list = self._list_ports(fields=['fixed_ips', 'mac_address']) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 409 | port_detail_list = [ |
| 410 | (port['fixed_ips'][0]['subnet_id'], |
| 411 | port['fixed_ips'][0]['ip_address'], |
Henry Gessau | 78ab4b0 | 2014-03-31 15:10:13 -0400 | [diff] [blame] | 412 | port['mac_address'].lower()) |
| 413 | for port in port_list if port['fixed_ips'] |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 414 | ] |
| 415 | server_ip = self._get_server_ip(tenant.access_point) |
| 416 | subnet_id = tenant.subnet.id |
| 417 | self.assertIn((subnet_id, server_ip, mac_addr), port_detail_list) |
| 418 | |
Chris Hoge | 7579c1a | 2015-02-26 14:12:15 -0800 | [diff] [blame] | 419 | @test.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848') |
Masayuki Igawa | 4ded9f0 | 2014-02-17 15:05:59 +0900 | [diff] [blame] | 420 | @test.services('compute', 'network') |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 421 | def test_cross_tenant_traffic(self): |
Andrea Frittoli (andreaf) | 1f34241 | 2015-05-12 16:37:19 +0100 | [diff] [blame] | 422 | if not self.credentials_provider.is_multi_tenant(): |
Yair Fried | 79b0a91 | 2014-10-20 11:15:37 +0300 | [diff] [blame] | 423 | raise self.skipException("No secondary tenant defined") |
Nachi Ueno | 26b4c97 | 2014-01-17 06:15:13 -0800 | [diff] [blame] | 424 | try: |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 425 | # deploy new tenant |
| 426 | self._deploy_tenant(self.alt_tenant) |
| 427 | self._verify_network_details(self.alt_tenant) |
| 428 | self._verify_mac_addr(self.alt_tenant) |
Yair Fried | 4d7efa6 | 2013-11-17 17:12:29 +0200 | [diff] [blame] | 429 | |
Nachi Ueno | 26b4c97 | 2014-01-17 06:15:13 -0800 | [diff] [blame] | 430 | # cross tenant check |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 431 | source_tenant = self.primary_tenant |
Nachi Ueno | 26b4c97 | 2014-01-17 06:15:13 -0800 | [diff] [blame] | 432 | dest_tenant = self.alt_tenant |
| 433 | self._test_cross_tenant_block(source_tenant, dest_tenant) |
| 434 | self._test_cross_tenant_allow(source_tenant, dest_tenant) |
| 435 | except Exception: |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 436 | for tenant in self.tenants.values(): |
| 437 | self._log_console_output(servers=tenant.servers) |
| 438 | raise |
| 439 | |
Chris Hoge | 7579c1a | 2015-02-26 14:12:15 -0800 | [diff] [blame] | 440 | @test.idempotent_id('63163892-bbf6-4249-aa12-d5ea1f8f421b') |
Masayuki Igawa | 4ded9f0 | 2014-02-17 15:05:59 +0900 | [diff] [blame] | 441 | @test.services('compute', 'network') |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 442 | def test_in_tenant_traffic(self): |
| 443 | try: |
| 444 | self._create_tenant_servers(self.primary_tenant, num=1) |
| 445 | |
| 446 | # in-tenant check |
| 447 | self._test_in_tenant_block(self.primary_tenant) |
| 448 | self._test_in_tenant_allow(self.primary_tenant) |
Rajkumar Thiyagarajan | d9e964a | 2014-12-17 01:55:52 -0800 | [diff] [blame] | 449 | except Exception: |
| 450 | for tenant in self.tenants.values(): |
| 451 | self._log_console_output(servers=tenant.servers) |
| 452 | raise |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 453 | |
Chris Hoge | 7579c1a | 2015-02-26 14:12:15 -0800 | [diff] [blame] | 454 | @test.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6') |
Rajkumar Thiyagarajan | d9e964a | 2014-12-17 01:55:52 -0800 | [diff] [blame] | 455 | @test.services('compute', 'network') |
| 456 | def test_port_update_new_security_group(self): |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 457 | """Verifies the traffic after updating the vm port |
| 458 | |
| 459 | With new security group having appropriate rule. |
Rajkumar Thiyagarajan | d9e964a | 2014-12-17 01:55:52 -0800 | [diff] [blame] | 460 | """ |
| 461 | new_tenant = self.primary_tenant |
| 462 | |
| 463 | # Create empty security group and add icmp rule in it |
| 464 | new_sg = self._create_empty_security_group( |
| 465 | namestart='secgroup_new-', |
| 466 | tenant_id=new_tenant.creds.tenant_id, |
| 467 | client=new_tenant.manager.network_client) |
| 468 | icmp_rule = dict( |
| 469 | protocol='icmp', |
| 470 | direction='ingress', |
| 471 | ) |
| 472 | self._create_security_group_rule( |
| 473 | secgroup=new_sg, |
| 474 | client=new_tenant.manager.network_client, |
| 475 | **icmp_rule) |
| 476 | new_tenant.security_groups.update(new_sg=new_sg) |
| 477 | |
| 478 | # Create server with default security group |
Ken'ichi Ohmichi | 6ded8df | 2015-03-23 02:00:19 +0000 | [diff] [blame] | 479 | name = 'server-{tenant}-gen-1'.format( |
Rajkumar Thiyagarajan | d9e964a | 2014-12-17 01:55:52 -0800 | [diff] [blame] | 480 | tenant=new_tenant.creds.tenant_name |
| 481 | ) |
| 482 | name = data_utils.rand_name(name) |
| 483 | server = self._create_server(name, new_tenant) |
| 484 | |
| 485 | # Check connectivity failure with default security group |
| 486 | try: |
| 487 | access_point_ssh = self._connect_to_access_point(new_tenant) |
| 488 | self._check_connectivity(access_point=access_point_ssh, |
| 489 | ip=self._get_server_ip(server), |
| 490 | should_succeed=False) |
| 491 | server_id = server['id'] |
| 492 | port_id = self._list_ports(device_id=server_id)[0]['id'] |
| 493 | |
| 494 | # update port with new security group and check connectivity |
John Warren | 49c0fe5 | 2015-10-22 12:35:54 -0400 | [diff] [blame] | 495 | self.ports_client.update_port(port_id, security_groups=[ |
Rajkumar Thiyagarajan | d9e964a | 2014-12-17 01:55:52 -0800 | [diff] [blame] | 496 | new_tenant.security_groups['new_sg'].id]) |
| 497 | self._check_connectivity( |
| 498 | access_point=access_point_ssh, |
| 499 | ip=self._get_server_ip(server)) |
Yair Fried | bf2e2c4 | 2014-01-28 12:06:38 +0200 | [diff] [blame] | 500 | except Exception: |
| 501 | for tenant in self.tenants.values(): |
| 502 | self._log_console_output(servers=tenant.servers) |
Nachi Ueno | 26b4c97 | 2014-01-17 06:15:13 -0800 | [diff] [blame] | 503 | raise |
prdsilva | 8b733ad | 2014-12-09 02:54:49 -0800 | [diff] [blame] | 504 | |
Chris Hoge | 7579c1a | 2015-02-26 14:12:15 -0800 | [diff] [blame] | 505 | @test.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293') |
prdsilva | 8b733ad | 2014-12-09 02:54:49 -0800 | [diff] [blame] | 506 | @test.services('compute', 'network') |
| 507 | def test_multiple_security_groups(self): |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 508 | """Verify multiple security groups and checks that rules |
| 509 | |
prdsilva | 8b733ad | 2014-12-09 02:54:49 -0800 | [diff] [blame] | 510 | provided in the both the groups is applied onto VM |
| 511 | """ |
| 512 | tenant = self.primary_tenant |
| 513 | ip = self._get_server_ip(tenant.access_point, |
| 514 | floating=self.floating_ip_access) |
lanoux | 283273b | 2015-12-04 03:01:54 -0800 | [diff] [blame] | 515 | ssh_login = CONF.validation.image_ssh_user |
prdsilva | 8b733ad | 2014-12-09 02:54:49 -0800 | [diff] [blame] | 516 | private_key = tenant.keypair['private_key'] |
| 517 | self.check_vm_connectivity(ip, |
| 518 | should_connect=False) |
| 519 | ruleset = dict( |
| 520 | protocol='icmp', |
| 521 | direction='ingress' |
| 522 | ) |
| 523 | self._create_security_group_rule( |
| 524 | secgroup=tenant.security_groups['default'], |
| 525 | **ruleset |
| 526 | ) |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 527 | # NOTE: Vm now has 2 security groups one with ssh rule( |
| 528 | # already added in setUp() method),and other with icmp rule |
| 529 | # (added in the above step).The check_vm_connectivity tests |
| 530 | # -that vm ping test is successful |
| 531 | # -ssh to vm is successful |
prdsilva | 8b733ad | 2014-12-09 02:54:49 -0800 | [diff] [blame] | 532 | self.check_vm_connectivity(ip, |
| 533 | username=ssh_login, |
| 534 | private_key=private_key, |
| 535 | should_connect=True) |
YAMAMOTO Takashi | 51e0408 | 2015-09-08 18:44:23 +0900 | [diff] [blame] | 536 | |
| 537 | @test.requires_ext(service='network', extension='port-security') |
| 538 | @test.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c') |
| 539 | @test.services('compute', 'network') |
| 540 | def test_port_security_disable_security_group(self): |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 541 | """Verify the default security group rules is disabled.""" |
YAMAMOTO Takashi | 51e0408 | 2015-09-08 18:44:23 +0900 | [diff] [blame] | 542 | new_tenant = self.primary_tenant |
| 543 | |
| 544 | # Create server |
| 545 | name = 'server-{tenant}-gen-1'.format( |
| 546 | tenant=new_tenant.creds.tenant_name |
| 547 | ) |
| 548 | name = data_utils.rand_name(name) |
| 549 | server = self._create_server(name, new_tenant) |
| 550 | |
| 551 | access_point_ssh = self._connect_to_access_point(new_tenant) |
| 552 | server_id = server['id'] |
| 553 | port_id = self._list_ports(device_id=server_id)[0]['id'] |
| 554 | |
| 555 | # Flip the port's port security and check connectivity |
| 556 | try: |
John Warren | 49c0fe5 | 2015-10-22 12:35:54 -0400 | [diff] [blame] | 557 | self.ports_client.update_port(port_id, |
| 558 | port_security_enabled=True, |
| 559 | security_groups=[]) |
YAMAMOTO Takashi | 51e0408 | 2015-09-08 18:44:23 +0900 | [diff] [blame] | 560 | self._check_connectivity(access_point=access_point_ssh, |
| 561 | ip=self._get_server_ip(server), |
| 562 | should_succeed=False) |
| 563 | |
John Warren | 49c0fe5 | 2015-10-22 12:35:54 -0400 | [diff] [blame] | 564 | self.ports_client.update_port(port_id, |
| 565 | port_security_enabled=False, |
| 566 | security_groups=[]) |
YAMAMOTO Takashi | 51e0408 | 2015-09-08 18:44:23 +0900 | [diff] [blame] | 567 | self._check_connectivity( |
| 568 | access_point=access_point_ssh, |
| 569 | ip=self._get_server_ip(server)) |
| 570 | except Exception: |
| 571 | for tenant in self.tenants.values(): |
| 572 | self._log_console_output(servers=tenant.servers) |
| 573 | raise |