blob: 2c16be89a9242aeb3f3ef137e0ac4399fbd971fd [file] [log] [blame]
Yair Fried4d7efa62013-11-17 17:12:29 +02001# 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.
Yair Friedca5cfb52016-01-04 15:41:55 +020015from oslo_log import log
Markus Zoeller156b5da2016-07-11 18:10:31 +020016import testtools
Yair Fried4d7efa62013-11-17 17:12:29 +020017
Andrea Frittolif9cde7e2014-02-18 09:57:04 +000018from tempest import clients
Fei Long Wangd39431f2015-05-14 11:30:48 +120019from tempest.common.utils import data_utils
Matthew Treinish6c072292014-01-29 19:15:52 +000020from tempest import config
Yair Fried4d7efa62013-11-17 17:12:29 +020021from tempest.scenario import manager
Masayuki Igawa4ded9f02014-02-17 15:05:59 +090022from tempest import test
Yair Fried4d7efa62013-11-17 17:12:29 +020023
Matthew Treinish6c072292014-01-29 19:15:52 +000024CONF = config.CONF
Yair Friedca5cfb52016-01-04 15:41:55 +020025LOG = log.getLogger(__name__)
Matthew Treinish6c072292014-01-29 19:15:52 +000026
Yair Fried4d7efa62013-11-17 17:12:29 +020027
Andrea Frittoli4971fc82014-09-25 10:22:20 +010028class TestSecurityGroupsBasicOps(manager.NetworkScenarioTest):
Yair Fried4d7efa62013-11-17 17:12:29 +020029
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +000030 """The test suite for security groups
31
Yair Fried4d7efa62013-11-17 17:12:29 +020032 This test suite assumes that Nova has been configured to
33 boot VM's with Neutron-managed networking, and attempts to
34 verify cross tenant connectivity as follows
35
36 ssh:
37 in order to overcome "ip namespace", each tenant has an "access point"
38 VM with floating-ip open to incoming ssh connection allowing network
39 commands (ping/ssh) to be executed from within the
40 tenant-network-namespace
41 Tempest host performs key-based authentication to the ssh server via
42 floating IP address
43
44 connectivity test is done by pinging destination server via source server
45 ssh connection.
46 success - ping returns
47 failure - ping_timeout reached
48
Eran Kurisb5f69782016-04-10 11:48:28 +030049 multi-node:
50 Multi-Node mode is enabled when CONF.compute.min_compute_nodes > 1.
51 Tests connectivity between servers on different compute nodes.
52 When enabled, test will boot each new server to different
53 compute nodes.
54
Yair Fried4d7efa62013-11-17 17:12:29 +020055 setup:
Yair Friedbf2e2c42014-01-28 12:06:38 +020056 for primary tenant:
Yair Fried4d7efa62013-11-17 17:12:29 +020057 1. create a network&subnet
58 2. create a router (if public router isn't configured)
59 3. connect tenant network to public network via router
60 4. create an access point:
61 a. a security group open to incoming ssh connection
62 b. a VM with a floating ip
63 5. create a general empty security group (same as "default", but
64 without rules allowing in-tenant traffic)
Yair Fried4d7efa62013-11-17 17:12:29 +020065
66 tests:
67 1. _verify_network_details
68 2. _verify_mac_addr: for each access point verify that
69 (subnet, fix_ip, mac address) are as defined in the port list
70 3. _test_in_tenant_block: test that in-tenant traffic is disabled
71 without rules allowing it
72 4. _test_in_tenant_allow: test that in-tenant traffic is enabled
73 once an appropriate rule has been created
74 5. _test_cross_tenant_block: test that cross-tenant traffic is disabled
75 without a rule allowing it on destination tenant
76 6. _test_cross_tenant_allow:
77 * test that cross-tenant traffic is enabled once an appropriate
78 rule has been created on destination tenant.
79 * test that reverse traffic is still blocked
Fei Long Wang50131ee2015-02-02 16:58:24 +130080 * test than reverse traffic is enabled once an appropriate rule has
Yair Fried4d7efa62013-11-17 17:12:29 +020081 been created on source tenant
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -080082 7._test_port_update_new_security_group:
83 * test that traffic is blocked with default security group
84 * test that traffic is enabled after updating port with new security
85 group having appropriate rule
prdsilva8b733ad2014-12-09 02:54:49 -080086 8. _test_multiple_security_groups: test multiple security groups can be
87 associated with the vm
Yair Fried4d7efa62013-11-17 17:12:29 +020088
89 assumptions:
Yair Friedbf2e2c42014-01-28 12:06:38 +020090 1. alt_tenant/user existed and is different from primary_tenant/user
Yair Fried4d7efa62013-11-17 17:12:29 +020091 2. Public network is defined and reachable from the Tempest host
92 3. Public router can either be:
93 * defined, in which case all tenants networks can connect directly
94 to it, and cross tenant check will be done on the private IP of the
95 destination tenant
96 or
Fei Long Wang50131ee2015-02-02 16:58:24 +130097 * not defined (empty string), in which case each tenant will have
Yair Fried4d7efa62013-11-17 17:12:29 +020098 its own router connected to the public network
99 """
100
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000101 credentials = ['primary', 'alt', 'admin']
102
Joe Gordon28788b42015-02-25 12:42:37 -0800103 class TenantProperties(object):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000104 """helper class to save tenant details
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000105
Yair Fried4d7efa62013-11-17 17:12:29 +0200106 id
107 credentials
108 network
109 subnet
110 security groups
111 servers
112 access point
Yair Friedbf2e2c42014-01-28 12:06:38 +0200113 """
Yair Fried4d7efa62013-11-17 17:12:29 +0200114
Andrea Frittoli422fbdf2014-03-20 10:05:18 +0000115 def __init__(self, credentials):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300116 self.manager = clients.Manager(credentials)
Andrea Frittoli422fbdf2014-03-20 10:05:18 +0000117 # Credentials from manager are filled with both names and IDs
118 self.creds = self.manager.credentials
Yair Fried4d7efa62013-11-17 17:12:29 +0200119 self.network = None
120 self.subnet = None
121 self.router = None
122 self.security_groups = {}
123 self.servers = list()
124
Yair Friedbf2e2c42014-01-28 12:06:38 +0200125 def set_network(self, network, subnet, router):
Yair Fried4d7efa62013-11-17 17:12:29 +0200126 self.network = network
127 self.subnet = subnet
128 self.router = router
129
Yair Fried4d7efa62013-11-17 17:12:29 +0200130 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000131 def skip_checks(cls):
132 super(TestSecurityGroupsBasicOps, cls).skip_checks()
Yair Frieddb6c9e92014-08-06 08:53:13 +0300133 if CONF.baremetal.driver_enabled:
134 msg = ('Not currently supported by baremetal.')
Yair Frieddb6c9e92014-08-06 08:53:13 +0300135 raise cls.skipException(msg)
Itzik Brown06952672015-03-29 12:38:58 +0300136 if CONF.network.port_vnic_type in ['direct', 'macvtap']:
137 msg = ('Not currently supported when using vnic_type'
138 ' direct or macvtap')
139 raise cls.skipException(msg)
Sean Dagueed6e5862016-04-04 10:49:13 -0400140 if not (CONF.network.project_networks_reachable or
Matthew Treinish6c072292014-01-29 19:15:52 +0000141 CONF.network.public_network_id):
Sean Dagueed6e5862016-04-04 10:49:13 -0400142 msg = ('Either project_networks_reachable must be "true", or '
Yair Fried4d7efa62013-11-17 17:12:29 +0200143 'public_network_id must be defined.')
Yair Fried4d7efa62013-11-17 17:12:29 +0200144 raise cls.skipException(msg)
Bence Romsics41f3f852016-01-11 13:48:23 +0100145 if not test.is_extension_enabled('security-group', 'network'):
146 msg = "security-group extension not enabled."
147 raise cls.skipException(msg)
Yair Fried4d7efa62013-11-17 17:12:29 +0200148
149 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000150 def setup_credentials(cls):
Yair Fried764610a2014-04-07 12:17:05 +0300151 # Create no network resources for these tests.
152 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000153 super(TestSecurityGroupsBasicOps, cls).setup_credentials()
Yair Fried4d7efa62013-11-17 17:12:29 +0200154 # TODO(mnewby) Consider looking up entities as needed instead
155 # of storing them as collections on the class.
Yair Fried79b0a912014-10-20 11:15:37 +0300156
Yair Fried79b0a912014-10-20 11:15:37 +0300157 # Credentials from the manager are filled with both IDs and Names
158 cls.alt_creds = cls.alt_manager.credentials
159
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000160 @classmethod
161 def resource_setup(cls):
162 super(TestSecurityGroupsBasicOps, cls).resource_setup()
Yair Friedca5cfb52016-01-04 15:41:55 +0200163
164 cls.multi_node = CONF.compute.min_compute_nodes > 1 and \
Yair Fried95914122016-03-03 09:14:40 +0200165 test.is_scheduler_filter_enabled("DifferentHostFilter")
Yair Friedca5cfb52016-01-04 15:41:55 +0200166 if cls.multi_node:
167 LOG.info("Working in Multi Node mode")
168 else:
169 LOG.info("Working in Single Node mode")
170
Yair Fried4d7efa62013-11-17 17:12:29 +0200171 cls.floating_ips = {}
172 cls.tenants = {}
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000173 creds = cls.manager.credentials
Andrea Frittoli422fbdf2014-03-20 10:05:18 +0000174 cls.primary_tenant = cls.TenantProperties(creds)
175 cls.alt_tenant = cls.TenantProperties(cls.alt_creds)
Yair Friedbf2e2c42014-01-28 12:06:38 +0200176 for tenant in [cls.primary_tenant, cls.alt_tenant]:
Andrea Frittoli86ad28d2014-03-20 10:09:12 +0000177 cls.tenants[tenant.creds.tenant_id] = tenant
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000178
Yair Friedbf2e2c42014-01-28 12:06:38 +0200179 cls.floating_ip_access = not CONF.network.public_router_id
Yair Fried4d7efa62013-11-17 17:12:29 +0200180
Yair Friedbf2e2c42014-01-28 12:06:38 +0200181 def setUp(self):
Yair Friedca5cfb52016-01-04 15:41:55 +0200182 """Set up a single tenant with an accessible server.
183
184 If multi-host is enabled, save created server uuids.
185 """
186 self.servers = []
187
Yair Friedbf2e2c42014-01-28 12:06:38 +0200188 super(TestSecurityGroupsBasicOps, self).setUp()
189 self._deploy_tenant(self.primary_tenant)
190 self._verify_network_details(self.primary_tenant)
191 self._verify_mac_addr(self.primary_tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200192
Yair Frieddb6c9e92014-08-06 08:53:13 +0300193 def _create_tenant_keypairs(self, tenant):
194 keypair = self.create_keypair(tenant.manager.keypairs_client)
195 tenant.keypair = keypair
Yair Fried4d7efa62013-11-17 17:12:29 +0200196
197 def _create_tenant_security_groups(self, tenant):
Yair Fried4d7efa62013-11-17 17:12:29 +0200198 access_sg = self._create_empty_security_group(
199 namestart='secgroup_access-',
Yair Frieddb6c9e92014-08-06 08:53:13 +0300200 tenant_id=tenant.creds.tenant_id,
John Warrenf9606e92015-12-10 12:12:42 -0500201 client=tenant.manager.security_groups_client
Yair Fried4d7efa62013-11-17 17:12:29 +0200202 )
Yair Friedbf2e2c42014-01-28 12:06:38 +0200203
Sean Dagueed6e5862016-04-04 10:49:13 -0400204 # don't use default secgroup since it allows in-project traffic
Yair Fried4d7efa62013-11-17 17:12:29 +0200205 def_sg = self._create_empty_security_group(
206 namestart='secgroup_general-',
Yair Frieddb6c9e92014-08-06 08:53:13 +0300207 tenant_id=tenant.creds.tenant_id,
John Warrenf9606e92015-12-10 12:12:42 -0500208 client=tenant.manager.security_groups_client
Yair Fried4d7efa62013-11-17 17:12:29 +0200209 )
210 tenant.security_groups.update(access=access_sg, default=def_sg)
211 ssh_rule = dict(
212 protocol='tcp',
213 port_range_min=22,
214 port_range_max=22,
215 direction='ingress',
216 )
John Warren456d9ae2016-01-12 15:36:33 -0500217 sec_group_rules_client = tenant.manager.security_group_rules_client
218 self._create_security_group_rule(
219 secgroup=access_sg,
220 sec_group_rules_client=sec_group_rules_client,
221 **ssh_rule)
Yair Fried4d7efa62013-11-17 17:12:29 +0200222
223 def _verify_network_details(self, tenant):
224 # Checks that we see the newly created network/subnet/router via
225 # checking the result of list_[networks,routers,subnets]
226 # Check that (router, subnet) couple exist in port_list
227 seen_nets = self._list_networks()
228 seen_names = [n['name'] for n in seen_nets]
229 seen_ids = [n['id'] for n in seen_nets]
230
Steve Heyman33735f22016-05-24 09:28:08 -0500231 self.assertIn(tenant.network['name'], seen_names)
232 self.assertIn(tenant.network['id'], seen_ids)
Yair Fried4d7efa62013-11-17 17:12:29 +0200233
234 seen_subnets = [(n['id'], n['cidr'], n['network_id'])
235 for n in self._list_subnets()]
Steve Heyman33735f22016-05-24 09:28:08 -0500236 mysubnet = (tenant.subnet['id'], tenant.subnet['cidr'],
237 tenant.network['id'])
Yair Fried4d7efa62013-11-17 17:12:29 +0200238 self.assertIn(mysubnet, seen_subnets)
239
240 seen_routers = self._list_routers()
241 seen_router_ids = [n['id'] for n in seen_routers]
242 seen_router_names = [n['name'] for n in seen_routers]
243
Steve Heyman33735f22016-05-24 09:28:08 -0500244 self.assertIn(tenant.router['name'], seen_router_names)
245 self.assertIn(tenant.router['id'], seen_router_ids)
Yair Fried4d7efa62013-11-17 17:12:29 +0200246
Steve Heyman33735f22016-05-24 09:28:08 -0500247 myport = (tenant.router['id'], tenant.subnet['id'])
Yair Fried4d7efa62013-11-17 17:12:29 +0200248 router_ports = [(i['device_id'], i['fixed_ips'][0]['subnet_id']) for i
Yair Frieddb6c9e92014-08-06 08:53:13 +0300249 in self._list_ports()
armando-migliacciobcfbbeb2014-08-11 18:33:47 -0700250 if self._is_router_port(i)]
Yair Fried4d7efa62013-11-17 17:12:29 +0200251
252 self.assertIn(myport, router_ports)
253
armando-migliacciobcfbbeb2014-08-11 18:33:47 -0700254 def _is_router_port(self, port):
255 """Return True if port is a router interface."""
256 # NOTE(armando-migliaccio): match device owner for both centralized
257 # and distributed routers; 'device_owner' is "" by default.
258 return port['device_owner'].startswith('network:router_interface')
259
Markus Zoeller156b5da2016-07-11 18:10:31 +0200260 def _create_server(self, name, tenant, security_groups, **kwargs):
Yair Friedca5cfb52016-01-04 15:41:55 +0200261 """Creates a server and assigns it to security group.
262
263 If multi-host is enabled, Ensures servers are created on different
264 compute nodes, by storing created servers' ids and uses different_host
265 as scheduler_hints on creation.
266 Validates servers are created as requested, using admin client.
267 """
Ken'ichi Ohmichi1b3461e2014-12-02 03:41:07 +0000268 security_groups_names = [{'name': s['name']} for s in security_groups]
Yair Friedca5cfb52016-01-04 15:41:55 +0200269 if self.multi_node:
270 kwargs["scheduler_hints"] = {'different_host': self.servers}
Ken'ichi Ohmichif2d436e2015-09-03 01:13:16 +0000271 server = self.create_server(
272 name=name,
Steve Heyman33735f22016-05-24 09:28:08 -0500273 networks=[{'uuid': tenant.network["id"]}],
lanoux5fc14522015-09-21 08:17:35 +0000274 key_name=tenant.keypair['name'],
275 security_groups=security_groups_names,
276 wait_until='ACTIVE',
Yair Friedca5cfb52016-01-04 15:41:55 +0200277 clients=tenant.manager,
278 **kwargs)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200279 if 'security_groups' in server:
280 self.assertEqual(
281 sorted([s['name'] for s in security_groups]),
282 sorted([s['name'] for s in server['security_groups']]))
Yair Friedca5cfb52016-01-04 15:41:55 +0200283
284 # Verify servers are on different compute nodes
285 if self.multi_node:
286 adm_get_server = self.admin_manager.servers_client.show_server
287 new_host = adm_get_server(server["id"])["server"][
288 "OS-EXT-SRV-ATTR:host"]
289 host_list = [adm_get_server(s)["server"]["OS-EXT-SRV-ATTR:host"]
290 for s in self.servers]
291 self.assertNotIn(new_host, host_list,
292 message="Failed to boot servers on different "
293 "Compute nodes.")
294
295 self.servers.append(server["id"])
296
Claudiu Belufaa98912014-09-01 16:50:28 +0300297 return server
Yair Fried4d7efa62013-11-17 17:12:29 +0200298
299 def _create_tenant_servers(self, tenant, num=1):
300 for i in range(num):
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000301 name = 'server-{tenant}-gen-{num}'.format(
Andrea Frittoli86ad28d2014-03-20 10:09:12 +0000302 tenant=tenant.creds.tenant_name,
Yair Fried4d7efa62013-11-17 17:12:29 +0200303 num=i
304 )
305 name = data_utils.rand_name(name)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200306 server = self._create_server(name, tenant,
307 [tenant.security_groups['default']])
Yair Fried4d7efa62013-11-17 17:12:29 +0200308 tenant.servers.append(server)
309
310 def _set_access_point(self, tenant):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000311 # creates a server in a secgroup with rule allowing external ssh
Sean Dagueed6e5862016-04-04 10:49:13 -0400312 # in order to access project internal network
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000313 # workaround ip namespace
Yair Frieddb6c9e92014-08-06 08:53:13 +0300314 secgroups = tenant.security_groups.values()
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000315 name = 'server-{tenant}-access_point'.format(
Andrea Frittoli86ad28d2014-03-20 10:09:12 +0000316 tenant=tenant.creds.tenant_name)
Yair Fried4d7efa62013-11-17 17:12:29 +0200317 name = data_utils.rand_name(name)
318 server = self._create_server(name, tenant,
319 security_groups=secgroups)
Yair Fried4d7efa62013-11-17 17:12:29 +0200320 tenant.access_point = server
Yair Frieddb6c9e92014-08-06 08:53:13 +0300321 self._assign_floating_ips(tenant, server)
Yair Fried4d7efa62013-11-17 17:12:29 +0200322
Yair Frieddb6c9e92014-08-06 08:53:13 +0300323 def _assign_floating_ips(self, tenant, server):
Matthew Treinish6c072292014-01-29 19:15:52 +0000324 public_network_id = CONF.network.public_network_id
Yair Friedae0e73d2014-11-24 11:56:26 +0200325 floating_ip = self.create_floating_ip(
Yair Frieddb6c9e92014-08-06 08:53:13 +0300326 server, public_network_id,
John Warrenfbf2a892015-11-17 12:36:14 -0500327 client=tenant.manager.floating_ips_client)
Yair Frieddb6c9e92014-08-06 08:53:13 +0300328 self.floating_ips.setdefault(server['id'], floating_ip)
Yair Fried4d7efa62013-11-17 17:12:29 +0200329
Markus Zoeller156b5da2016-07-11 18:10:31 +0200330 def _create_tenant_network(self, tenant, port_security_enabled=True):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300331 network, subnet, router = self.create_networks(
John Warren3961acd2015-10-02 14:38:53 -0400332 networks_client=tenant.manager.networks_client,
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000333 routers_client=tenant.manager.routers_client,
Markus Zoeller156b5da2016-07-11 18:10:31 +0200334 subnets_client=tenant.manager.subnets_client,
335 port_security_enabled=port_security_enabled)
Yair Friedbf2e2c42014-01-28 12:06:38 +0200336 tenant.set_network(network, subnet, router)
Yair Fried4d7efa62013-11-17 17:12:29 +0200337
Yair Fried4d7efa62013-11-17 17:12:29 +0200338 def _deploy_tenant(self, tenant_or_id):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000339 """creates:
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000340
Yair Fried4d7efa62013-11-17 17:12:29 +0200341 network
342 subnet
343 router (if public not defined)
344 access security group
345 access-point server
Yair Fried4d7efa62013-11-17 17:12:29 +0200346 """
347 if not isinstance(tenant_or_id, self.TenantProperties):
348 tenant = self.tenants[tenant_or_id]
Yair Fried4d7efa62013-11-17 17:12:29 +0200349 else:
350 tenant = tenant_or_id
Yair Frieddb6c9e92014-08-06 08:53:13 +0300351 self._create_tenant_keypairs(tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200352 self._create_tenant_network(tenant)
353 self._create_tenant_security_groups(tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200354 self._set_access_point(tenant)
355
356 def _get_server_ip(self, server, floating=False):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000357 """returns the ip (floating/internal) of a server"""
Yair Fried4d7efa62013-11-17 17:12:29 +0200358 if floating:
Steve Heyman33735f22016-05-24 09:28:08 -0500359 server_ip = self.floating_ips[server['id']]['floating_ip_address']
Yair Fried4d7efa62013-11-17 17:12:29 +0200360 else:
armando-migliacciod03f2642014-02-21 19:55:50 -0800361 server_ip = None
Steve Heyman33735f22016-05-24 09:28:08 -0500362 network_name = self.tenants[server['tenant_id']].network['name']
Yair Frieddb6c9e92014-08-06 08:53:13 +0300363 if network_name in server['addresses']:
364 server_ip = server['addresses'][network_name][0]['addr']
armando-migliacciod03f2642014-02-21 19:55:50 -0800365 return server_ip
Yair Fried4d7efa62013-11-17 17:12:29 +0200366
367 def _connect_to_access_point(self, tenant):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000368 """create ssh connection to tenant access point"""
Yair Fried4d7efa62013-11-17 17:12:29 +0200369 access_point_ssh = \
Steve Heyman33735f22016-05-24 09:28:08 -0500370 self.floating_ips[tenant.access_point['id']]['floating_ip_address']
Yair Frieddb6c9e92014-08-06 08:53:13 +0300371 private_key = tenant.keypair['private_key']
Jordan Pittierbbb17122016-01-26 17:10:55 +0100372 access_point_ssh = self.get_remote_client(
373 access_point_ssh, private_key=private_key)
Yair Fried4d7efa62013-11-17 17:12:29 +0200374 return access_point_ssh
375
Yair Fried4d7efa62013-11-17 17:12:29 +0200376 def _check_connectivity(self, access_point, ip, should_succeed=True):
377 if should_succeed:
378 msg = "Timed out waiting for %s to become reachable" % ip
379 else:
Yair Fried4d7efa62013-11-17 17:12:29 +0200380 msg = "%s is reachable" % ip
Matthew Treinish53483132014-12-09 18:50:06 -0500381 self.assertTrue(self._check_remote_connectivity(access_point, ip,
382 should_succeed), msg)
Yair Fried4d7efa62013-11-17 17:12:29 +0200383
384 def _test_in_tenant_block(self, tenant):
385 access_point_ssh = self._connect_to_access_point(tenant)
386 for server in tenant.servers:
387 self._check_connectivity(access_point=access_point_ssh,
388 ip=self._get_server_ip(server),
389 should_succeed=False)
390
391 def _test_in_tenant_allow(self, tenant):
392 ruleset = dict(
393 protocol='icmp',
Steve Heyman33735f22016-05-24 09:28:08 -0500394 remote_group_id=tenant.security_groups['default']['id'],
Yair Fried4d7efa62013-11-17 17:12:29 +0200395 direction='ingress'
396 )
Matthew Treinishb7144eb2013-12-13 22:57:35 +0000397 self._create_security_group_rule(
Yair Fried4d7efa62013-11-17 17:12:29 +0200398 secgroup=tenant.security_groups['default'],
Yair Friedca5cfb52016-01-04 15:41:55 +0200399 security_groups_client=tenant.manager.security_groups_client,
Yair Fried4d7efa62013-11-17 17:12:29 +0200400 **ruleset
401 )
402 access_point_ssh = self._connect_to_access_point(tenant)
403 for server in tenant.servers:
404 self._check_connectivity(access_point=access_point_ssh,
405 ip=self._get_server_ip(server))
Yair Fried4d7efa62013-11-17 17:12:29 +0200406
407 def _test_cross_tenant_block(self, source_tenant, dest_tenant):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000408 # if public router isn't defined, then dest_tenant access is via
409 # floating-ip
Yair Fried4d7efa62013-11-17 17:12:29 +0200410 access_point_ssh = self._connect_to_access_point(source_tenant)
411 ip = self._get_server_ip(dest_tenant.access_point,
412 floating=self.floating_ip_access)
413 self._check_connectivity(access_point=access_point_ssh, ip=ip,
414 should_succeed=False)
415
416 def _test_cross_tenant_allow(self, source_tenant, dest_tenant):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000417 """check for each direction:
418
Yair Fried4d7efa62013-11-17 17:12:29 +0200419 creating rule for tenant incoming traffic enables only 1way traffic
Yair Friedbf2e2c42014-01-28 12:06:38 +0200420 """
Yair Fried4d7efa62013-11-17 17:12:29 +0200421 ruleset = dict(
422 protocol='icmp',
423 direction='ingress'
424 )
John Warren456d9ae2016-01-12 15:36:33 -0500425 sec_group_rules_client = (
426 dest_tenant.manager.security_group_rules_client)
Matthew Treinishb7144eb2013-12-13 22:57:35 +0000427 self._create_security_group_rule(
Yair Fried4d7efa62013-11-17 17:12:29 +0200428 secgroup=dest_tenant.security_groups['default'],
John Warren456d9ae2016-01-12 15:36:33 -0500429 sec_group_rules_client=sec_group_rules_client,
Yair Fried4d7efa62013-11-17 17:12:29 +0200430 **ruleset
431 )
Yair Friedbf2e2c42014-01-28 12:06:38 +0200432 access_point_ssh = self._connect_to_access_point(source_tenant)
433 ip = self._get_server_ip(dest_tenant.access_point,
434 floating=self.floating_ip_access)
435 self._check_connectivity(access_point_ssh, ip)
Yair Fried4d7efa62013-11-17 17:12:29 +0200436
Yair Friedbf2e2c42014-01-28 12:06:38 +0200437 # test that reverse traffic is still blocked
438 self._test_cross_tenant_block(dest_tenant, source_tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200439
Yair Friedbf2e2c42014-01-28 12:06:38 +0200440 # allow reverse traffic and check
John Warren456d9ae2016-01-12 15:36:33 -0500441 sec_group_rules_client = (
442 source_tenant.manager.security_group_rules_client)
Matthew Treinishb7144eb2013-12-13 22:57:35 +0000443 self._create_security_group_rule(
Yair Friedbf2e2c42014-01-28 12:06:38 +0200444 secgroup=source_tenant.security_groups['default'],
John Warren456d9ae2016-01-12 15:36:33 -0500445 sec_group_rules_client=sec_group_rules_client,
Yair Friedbf2e2c42014-01-28 12:06:38 +0200446 **ruleset
447 )
Yair Fried4d7efa62013-11-17 17:12:29 +0200448
Yair Friedbf2e2c42014-01-28 12:06:38 +0200449 access_point_ssh_2 = self._connect_to_access_point(dest_tenant)
450 ip = self._get_server_ip(source_tenant.access_point,
451 floating=self.floating_ip_access)
452 self._check_connectivity(access_point_ssh_2, ip)
Yair Fried4d7efa62013-11-17 17:12:29 +0200453
454 def _verify_mac_addr(self, tenant):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000455 """Verify that VM has the same ip, mac as listed in port"""
456
Yair Fried4d7efa62013-11-17 17:12:29 +0200457 access_point_ssh = self._connect_to_access_point(tenant)
458 mac_addr = access_point_ssh.get_mac_address()
459 mac_addr = mac_addr.strip().lower()
Henry Gessau78ab4b02014-03-31 15:10:13 -0400460 # Get the fixed_ips and mac_address fields of all ports. Select
461 # only those two columns to reduce the size of the response.
Yair Frieddb6c9e92014-08-06 08:53:13 +0300462 port_list = self._list_ports(fields=['fixed_ips', 'mac_address'])
Yair Fried4d7efa62013-11-17 17:12:29 +0200463 port_detail_list = [
464 (port['fixed_ips'][0]['subnet_id'],
465 port['fixed_ips'][0]['ip_address'],
Henry Gessau78ab4b02014-03-31 15:10:13 -0400466 port['mac_address'].lower())
467 for port in port_list if port['fixed_ips']
Yair Fried4d7efa62013-11-17 17:12:29 +0200468 ]
469 server_ip = self._get_server_ip(tenant.access_point)
Steve Heyman33735f22016-05-24 09:28:08 -0500470 subnet_id = tenant.subnet['id']
Yair Fried4d7efa62013-11-17 17:12:29 +0200471 self.assertIn((subnet_id, server_ip, mac_addr), port_detail_list)
472
Chris Hoge7579c1a2015-02-26 14:12:15 -0800473 @test.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
Masayuki Igawa4ded9f02014-02-17 15:05:59 +0900474 @test.services('compute', 'network')
Yair Fried4d7efa62013-11-17 17:12:29 +0200475 def test_cross_tenant_traffic(self):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100476 if not self.credentials_provider.is_multi_tenant():
Yair Fried79b0a912014-10-20 11:15:37 +0300477 raise self.skipException("No secondary tenant defined")
Nachi Ueno26b4c972014-01-17 06:15:13 -0800478 try:
Sean Dagueed6e5862016-04-04 10:49:13 -0400479 # deploy new project
Yair Friedbf2e2c42014-01-28 12:06:38 +0200480 self._deploy_tenant(self.alt_tenant)
481 self._verify_network_details(self.alt_tenant)
482 self._verify_mac_addr(self.alt_tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200483
Nachi Ueno26b4c972014-01-17 06:15:13 -0800484 # cross tenant check
Yair Friedbf2e2c42014-01-28 12:06:38 +0200485 source_tenant = self.primary_tenant
Nachi Ueno26b4c972014-01-17 06:15:13 -0800486 dest_tenant = self.alt_tenant
487 self._test_cross_tenant_block(source_tenant, dest_tenant)
488 self._test_cross_tenant_allow(source_tenant, dest_tenant)
489 except Exception:
Yair Friedbf2e2c42014-01-28 12:06:38 +0200490 for tenant in self.tenants.values():
491 self._log_console_output(servers=tenant.servers)
492 raise
493
Chris Hoge7579c1a2015-02-26 14:12:15 -0800494 @test.idempotent_id('63163892-bbf6-4249-aa12-d5ea1f8f421b')
Masayuki Igawa4ded9f02014-02-17 15:05:59 +0900495 @test.services('compute', 'network')
Yair Friedbf2e2c42014-01-28 12:06:38 +0200496 def test_in_tenant_traffic(self):
497 try:
498 self._create_tenant_servers(self.primary_tenant, num=1)
499
500 # in-tenant check
501 self._test_in_tenant_block(self.primary_tenant)
502 self._test_in_tenant_allow(self.primary_tenant)
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800503 except Exception:
504 for tenant in self.tenants.values():
505 self._log_console_output(servers=tenant.servers)
506 raise
Yair Friedbf2e2c42014-01-28 12:06:38 +0200507
Chris Hoge7579c1a2015-02-26 14:12:15 -0800508 @test.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800509 @test.services('compute', 'network')
510 def test_port_update_new_security_group(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000511 """Verifies the traffic after updating the vm port
512
513 With new security group having appropriate rule.
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800514 """
515 new_tenant = self.primary_tenant
516
517 # Create empty security group and add icmp rule in it
518 new_sg = self._create_empty_security_group(
519 namestart='secgroup_new-',
520 tenant_id=new_tenant.creds.tenant_id,
John Warrenf9606e92015-12-10 12:12:42 -0500521 client=new_tenant.manager.security_groups_client)
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800522 icmp_rule = dict(
523 protocol='icmp',
524 direction='ingress',
525 )
John Warren456d9ae2016-01-12 15:36:33 -0500526 sec_group_rules_client = new_tenant.manager.security_group_rules_client
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800527 self._create_security_group_rule(
528 secgroup=new_sg,
John Warren456d9ae2016-01-12 15:36:33 -0500529 sec_group_rules_client=sec_group_rules_client,
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800530 **icmp_rule)
531 new_tenant.security_groups.update(new_sg=new_sg)
532
533 # Create server with default security group
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000534 name = 'server-{tenant}-gen-1'.format(
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800535 tenant=new_tenant.creds.tenant_name
536 )
537 name = data_utils.rand_name(name)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200538 server = self._create_server(name, new_tenant,
539 [new_tenant.security_groups['default']])
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800540
541 # Check connectivity failure with default security group
542 try:
543 access_point_ssh = self._connect_to_access_point(new_tenant)
544 self._check_connectivity(access_point=access_point_ssh,
545 ip=self._get_server_ip(server),
546 should_succeed=False)
547 server_id = server['id']
548 port_id = self._list_ports(device_id=server_id)[0]['id']
549
550 # update port with new security group and check connectivity
John Warren49c0fe52015-10-22 12:35:54 -0400551 self.ports_client.update_port(port_id, security_groups=[
Steve Heyman33735f22016-05-24 09:28:08 -0500552 new_tenant.security_groups['new_sg']['id']])
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800553 self._check_connectivity(
554 access_point=access_point_ssh,
555 ip=self._get_server_ip(server))
Yair Friedbf2e2c42014-01-28 12:06:38 +0200556 except Exception:
557 for tenant in self.tenants.values():
558 self._log_console_output(servers=tenant.servers)
Nachi Ueno26b4c972014-01-17 06:15:13 -0800559 raise
prdsilva8b733ad2014-12-09 02:54:49 -0800560
Chris Hoge7579c1a2015-02-26 14:12:15 -0800561 @test.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
prdsilva8b733ad2014-12-09 02:54:49 -0800562 @test.services('compute', 'network')
563 def test_multiple_security_groups(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000564 """Verify multiple security groups and checks that rules
565
prdsilva8b733ad2014-12-09 02:54:49 -0800566 provided in the both the groups is applied onto VM
567 """
568 tenant = self.primary_tenant
569 ip = self._get_server_ip(tenant.access_point,
570 floating=self.floating_ip_access)
lanoux283273b2015-12-04 03:01:54 -0800571 ssh_login = CONF.validation.image_ssh_user
prdsilva8b733ad2014-12-09 02:54:49 -0800572 private_key = tenant.keypair['private_key']
573 self.check_vm_connectivity(ip,
574 should_connect=False)
575 ruleset = dict(
576 protocol='icmp',
577 direction='ingress'
578 )
579 self._create_security_group_rule(
580 secgroup=tenant.security_groups['default'],
581 **ruleset
582 )
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000583 # NOTE: Vm now has 2 security groups one with ssh rule(
584 # already added in setUp() method),and other with icmp rule
585 # (added in the above step).The check_vm_connectivity tests
586 # -that vm ping test is successful
587 # -ssh to vm is successful
prdsilva8b733ad2014-12-09 02:54:49 -0800588 self.check_vm_connectivity(ip,
589 username=ssh_login,
590 private_key=private_key,
591 should_connect=True)
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900592
593 @test.requires_ext(service='network', extension='port-security')
594 @test.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
595 @test.services('compute', 'network')
596 def test_port_security_disable_security_group(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000597 """Verify the default security group rules is disabled."""
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900598 new_tenant = self.primary_tenant
599
600 # Create server
601 name = 'server-{tenant}-gen-1'.format(
602 tenant=new_tenant.creds.tenant_name
603 )
604 name = data_utils.rand_name(name)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200605 server = self._create_server(name, new_tenant,
606 [new_tenant.security_groups['default']])
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900607
608 access_point_ssh = self._connect_to_access_point(new_tenant)
609 server_id = server['id']
610 port_id = self._list_ports(device_id=server_id)[0]['id']
611
612 # Flip the port's port security and check connectivity
613 try:
John Warren49c0fe52015-10-22 12:35:54 -0400614 self.ports_client.update_port(port_id,
615 port_security_enabled=True,
616 security_groups=[])
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900617 self._check_connectivity(access_point=access_point_ssh,
618 ip=self._get_server_ip(server),
619 should_succeed=False)
620
John Warren49c0fe52015-10-22 12:35:54 -0400621 self.ports_client.update_port(port_id,
622 port_security_enabled=False,
623 security_groups=[])
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900624 self._check_connectivity(
625 access_point=access_point_ssh,
626 ip=self._get_server_ip(server))
627 except Exception:
628 for tenant in self.tenants.values():
629 self._log_console_output(servers=tenant.servers)
630 raise
Markus Zoeller156b5da2016-07-11 18:10:31 +0200631
632 @test.requires_ext(service='network', extension='port-security')
633 @test.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
634 @testtools.skipUnless(
635 CONF.compute_feature_enabled.allow_port_security_disabled,
636 'Port security must be enabled.')
Matt Riedemann039b2fe2016-09-15 16:12:24 -0400637 # TODO(mriedem): We shouldn't actually need to check this since neutron
638 # disables the port_security extension by default, but the problem is nova
639 # assumes port_security_enabled=True if it's not set on the network
640 # resource, which will mean nova may attempt to apply a security group on
641 # a port on that network which would fail. This is really a bug in nova.
642 @testtools.skipUnless(
643 CONF.network_feature_enabled.port_security,
644 'Port security must be enabled.')
Markus Zoeller156b5da2016-07-11 18:10:31 +0200645 @test.services('compute', 'network')
646 def test_boot_into_disabled_port_security_network_without_secgroup(self):
647 tenant = self.primary_tenant
648 self._create_tenant_network(tenant, port_security_enabled=False)
649 self.assertFalse(tenant.network['port_security_enabled'])
650 name = data_utils.rand_name('server-smoke')
651 sec_groups = []
652 server = self._create_server(name, tenant, sec_groups)
653 server_id = server['id']
654 ports = self._list_ports(device_id=server_id)
655 self.assertEqual(1, len(ports))
656 for port in ports:
657 self.assertEmpty(port['security_groups'],
658 "Neutron shouldn't even use it's default sec "
659 "group.")