blob: 03a4a397ecd43653b987346c91d25741fab58a6a [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 Frittoli88eb6772017-08-07 21:06:27 +010018from tempest.common import compute
Andrea Frittolicd368412017-08-14 21:37:56 +010019from tempest.common import utils
Attila Fazekasd7e08a62016-10-07 13:05:05 +020020from tempest.common.utils import net_info
Matthew Treinish6c072292014-01-29 19:15:52 +000021from tempest import config
Ken'ichi Ohmichibe4fb502017-03-10 10:04:48 -080022from tempest.lib.common.utils import data_utils
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -080023from tempest.lib import decorators
Yair Fried4d7efa62013-11-17 17:12:29 +020024from tempest.scenario import manager
Yair Fried4d7efa62013-11-17 17:12:29 +020025
Matthew Treinish6c072292014-01-29 19:15:52 +000026CONF = config.CONF
Yair Friedca5cfb52016-01-04 15:41:55 +020027LOG = log.getLogger(__name__)
Matthew Treinish6c072292014-01-29 19:15:52 +000028
Yair Fried4d7efa62013-11-17 17:12:29 +020029
Andrea Frittoli4971fc82014-09-25 10:22:20 +010030class TestSecurityGroupsBasicOps(manager.NetworkScenarioTest):
Yair Fried4d7efa62013-11-17 17:12:29 +020031
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +000032 """The test suite for security groups
33
Yair Fried4d7efa62013-11-17 17:12:29 +020034 This test suite assumes that Nova has been configured to
35 boot VM's with Neutron-managed networking, and attempts to
36 verify cross tenant connectivity as follows
37
38 ssh:
39 in order to overcome "ip namespace", each tenant has an "access point"
40 VM with floating-ip open to incoming ssh connection allowing network
41 commands (ping/ssh) to be executed from within the
42 tenant-network-namespace
43 Tempest host performs key-based authentication to the ssh server via
44 floating IP address
45
46 connectivity test is done by pinging destination server via source server
47 ssh connection.
48 success - ping returns
49 failure - ping_timeout reached
50
Eran Kurisb5f69782016-04-10 11:48:28 +030051 multi-node:
52 Multi-Node mode is enabled when CONF.compute.min_compute_nodes > 1.
53 Tests connectivity between servers on different compute nodes.
54 When enabled, test will boot each new server to different
55 compute nodes.
56
Yair Fried4d7efa62013-11-17 17:12:29 +020057 setup:
Yair Friedbf2e2c42014-01-28 12:06:38 +020058 for primary tenant:
Yair Fried4d7efa62013-11-17 17:12:29 +020059 1. create a network&subnet
60 2. create a router (if public router isn't configured)
61 3. connect tenant network to public network via router
62 4. create an access point:
63 a. a security group open to incoming ssh connection
64 b. a VM with a floating ip
65 5. create a general empty security group (same as "default", but
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060066 without rules allowing in-tenant traffic)
Yair Fried4d7efa62013-11-17 17:12:29 +020067
68 tests:
69 1. _verify_network_details
70 2. _verify_mac_addr: for each access point verify that
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060071 (subnet, fix_ip, mac address) are as defined in the port list
Yair Fried4d7efa62013-11-17 17:12:29 +020072 3. _test_in_tenant_block: test that in-tenant traffic is disabled
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060073 without rules allowing it
Yair Fried4d7efa62013-11-17 17:12:29 +020074 4. _test_in_tenant_allow: test that in-tenant traffic is enabled
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060075 once an appropriate rule has been created
Yair Fried4d7efa62013-11-17 17:12:29 +020076 5. _test_cross_tenant_block: test that cross-tenant traffic is disabled
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060077 without a rule allowing it on destination tenant
Yair Fried4d7efa62013-11-17 17:12:29 +020078 6. _test_cross_tenant_allow:
79 * test that cross-tenant traffic is enabled once an appropriate
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060080 rule has been created on destination tenant.
Yair Fried4d7efa62013-11-17 17:12:29 +020081 * test that reverse traffic is still blocked
Fei Long Wang50131ee2015-02-02 16:58:24 +130082 * test than reverse traffic is enabled once an appropriate rule has
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060083 been created on source tenant
84 7. _test_port_update_new_security_group:
85 * test that traffic is blocked with default security group
86 * test that traffic is enabled after updating port with new
87 security group having appropriate rule
prdsilva8b733ad2014-12-09 02:54:49 -080088 8. _test_multiple_security_groups: test multiple security groups can be
89 associated with the vm
Yair Fried4d7efa62013-11-17 17:12:29 +020090
91 assumptions:
Yair Friedbf2e2c42014-01-28 12:06:38 +020092 1. alt_tenant/user existed and is different from primary_tenant/user
Yair Fried4d7efa62013-11-17 17:12:29 +020093 2. Public network is defined and reachable from the Tempest host
94 3. Public router can either be:
95 * defined, in which case all tenants networks can connect directly
Sergey Vilgelmeac094a2018-11-21 18:27:51 -060096 to it, and cross tenant check will be done on the private IP of
97 the destination tenant
98
Yair Fried4d7efa62013-11-17 17:12:29 +020099 or
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600100
Fei Long Wang50131ee2015-02-02 16:58:24 +1300101 * not defined (empty string), in which case each tenant will have
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600102 its own router connected to the public network
Yair Fried4d7efa62013-11-17 17:12:29 +0200103 """
104
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000105 credentials = ['primary', 'alt', 'admin']
106
Joe Gordon28788b42015-02-25 12:42:37 -0800107 class TenantProperties(object):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000108 """helper class to save tenant details
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000109
Yair Fried4d7efa62013-11-17 17:12:29 +0200110 id
111 credentials
112 network
113 subnet
114 security groups
115 servers
116 access point
Yair Friedbf2e2c42014-01-28 12:06:38 +0200117 """
Yair Fried4d7efa62013-11-17 17:12:29 +0200118
Andrea Frittoli73224672016-12-09 21:08:19 +0000119 def __init__(self, clients):
Andrea Frittoli422fbdf2014-03-20 10:05:18 +0000120 # Credentials from manager are filled with both names and IDs
Andrea Frittoli73224672016-12-09 21:08:19 +0000121 self.manager = clients
Andrea Frittoli422fbdf2014-03-20 10:05:18 +0000122 self.creds = self.manager.credentials
Yair Fried4d7efa62013-11-17 17:12:29 +0200123 self.network = None
124 self.subnet = None
125 self.router = None
126 self.security_groups = {}
127 self.servers = list()
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700128 self.access_point = None
Yair Fried4d7efa62013-11-17 17:12:29 +0200129
Yair Friedbf2e2c42014-01-28 12:06:38 +0200130 def set_network(self, network, subnet, router):
Yair Fried4d7efa62013-11-17 17:12:29 +0200131 self.network = network
132 self.subnet = subnet
133 self.router = router
134
Yair Fried4d7efa62013-11-17 17:12:29 +0200135 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000136 def skip_checks(cls):
137 super(TestSecurityGroupsBasicOps, cls).skip_checks()
Itzik Brown06952672015-03-29 12:38:58 +0300138 if CONF.network.port_vnic_type in ['direct', 'macvtap']:
139 msg = ('Not currently supported when using vnic_type'
140 ' direct or macvtap')
141 raise cls.skipException(msg)
Sean Dagueed6e5862016-04-04 10:49:13 -0400142 if not (CONF.network.project_networks_reachable or
Matthew Treinish6c072292014-01-29 19:15:52 +0000143 CONF.network.public_network_id):
Sean Dagueed6e5862016-04-04 10:49:13 -0400144 msg = ('Either project_networks_reachable must be "true", or '
Yair Fried4d7efa62013-11-17 17:12:29 +0200145 'public_network_id must be defined.')
Yair Fried4d7efa62013-11-17 17:12:29 +0200146 raise cls.skipException(msg)
Andrea Frittolicd368412017-08-14 21:37:56 +0100147 if not utils.is_extension_enabled('security-group', 'network'):
Bence Romsics41f3f852016-01-11 13:48:23 +0100148 msg = "security-group extension not enabled."
149 raise cls.skipException(msg)
ghanshyam929b3482016-12-05 11:47:53 +0900150 if CONF.network.shared_physical_network:
Thiago Paiva66cded22016-08-15 14:55:58 -0300151 msg = ('Deployment uses a shared physical network, security '
152 'groups not supported')
153 raise cls.skipException(msg)
Matthew Treinish3312de32017-05-19 12:08:17 -0400154 if not CONF.network_feature_enabled.floating_ips:
155 raise cls.skipException("Floating ips are not available")
Yair Fried4d7efa62013-11-17 17:12:29 +0200156
157 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000158 def setup_credentials(cls):
Yair Fried764610a2014-04-07 12:17:05 +0300159 # Create no network resources for these tests.
160 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000161 super(TestSecurityGroupsBasicOps, cls).setup_credentials()
Yair Fried79b0a912014-10-20 11:15:37 +0300162
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000163 @classmethod
164 def resource_setup(cls):
165 super(TestSecurityGroupsBasicOps, cls).resource_setup()
Yair Friedca5cfb52016-01-04 15:41:55 +0200166
167 cls.multi_node = CONF.compute.min_compute_nodes > 1 and \
Andrea Frittoli88eb6772017-08-07 21:06:27 +0100168 compute.is_scheduler_filter_enabled("DifferentHostFilter")
Yair Friedca5cfb52016-01-04 15:41:55 +0200169 if cls.multi_node:
170 LOG.info("Working in Multi Node mode")
171 else:
172 LOG.info("Working in Single Node mode")
173
Yair Fried4d7efa62013-11-17 17:12:29 +0200174 cls.floating_ips = {}
175 cls.tenants = {}
zhufl04190882017-05-23 10:21:48 +0800176 cls.primary_tenant = cls.TenantProperties(cls.os_primary)
Andrea Frittoli73224672016-12-09 21:08:19 +0000177 cls.alt_tenant = cls.TenantProperties(cls.os_alt)
Yair Friedbf2e2c42014-01-28 12:06:38 +0200178 for tenant in [cls.primary_tenant, cls.alt_tenant]:
Rodolfo Alonso Hernandezc1449d42020-02-15 13:24:28 +0000179 cls.tenants[tenant.creds.project_id] = tenant
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000180
Yair Friedbf2e2c42014-01-28 12:06:38 +0200181 cls.floating_ip_access = not CONF.network.public_router_id
Yair Fried4d7efa62013-11-17 17:12:29 +0200182
Yair Friedbf2e2c42014-01-28 12:06:38 +0200183 def setUp(self):
Yair Friedca5cfb52016-01-04 15:41:55 +0200184 """Set up a single tenant with an accessible server.
185
186 If multi-host is enabled, save created server uuids.
187 """
188 self.servers = []
189
Yair Friedbf2e2c42014-01-28 12:06:38 +0200190 super(TestSecurityGroupsBasicOps, self).setUp()
191 self._deploy_tenant(self.primary_tenant)
192 self._verify_network_details(self.primary_tenant)
193 self._verify_mac_addr(self.primary_tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200194
Yair Frieddb6c9e92014-08-06 08:53:13 +0300195 def _create_tenant_keypairs(self, tenant):
196 keypair = self.create_keypair(tenant.manager.keypairs_client)
197 tenant.keypair = keypair
Yair Fried4d7efa62013-11-17 17:12:29 +0200198
199 def _create_tenant_security_groups(self, tenant):
Yair Fried4d7efa62013-11-17 17:12:29 +0200200 access_sg = self._create_empty_security_group(
201 namestart='secgroup_access-',
Rodolfo Alonso Hernandezc1449d42020-02-15 13:24:28 +0000202 project_id=tenant.creds.project_id,
John Warrenf9606e92015-12-10 12:12:42 -0500203 client=tenant.manager.security_groups_client
Yair Fried4d7efa62013-11-17 17:12:29 +0200204 )
Yair Friedbf2e2c42014-01-28 12:06:38 +0200205
Sean Dagueed6e5862016-04-04 10:49:13 -0400206 # don't use default secgroup since it allows in-project traffic
Yair Fried4d7efa62013-11-17 17:12:29 +0200207 def_sg = self._create_empty_security_group(
208 namestart='secgroup_general-',
Rodolfo Alonso Hernandezc1449d42020-02-15 13:24:28 +0000209 project_id=tenant.creds.project_id,
John Warrenf9606e92015-12-10 12:12:42 -0500210 client=tenant.manager.security_groups_client
Yair Fried4d7efa62013-11-17 17:12:29 +0200211 )
212 tenant.security_groups.update(access=access_sg, default=def_sg)
213 ssh_rule = dict(
214 protocol='tcp',
215 port_range_min=22,
216 port_range_max=22,
217 direction='ingress',
218 )
John Warren456d9ae2016-01-12 15:36:33 -0500219 sec_group_rules_client = tenant.manager.security_group_rules_client
220 self._create_security_group_rule(
221 secgroup=access_sg,
222 sec_group_rules_client=sec_group_rules_client,
223 **ssh_rule)
Yair Fried4d7efa62013-11-17 17:12:29 +0200224
225 def _verify_network_details(self, tenant):
226 # Checks that we see the newly created network/subnet/router via
227 # checking the result of list_[networks,routers,subnets]
228 # Check that (router, subnet) couple exist in port_list
jeremy.zhang5870ff12017-05-25 11:24:23 +0800229 seen_nets = self.os_admin.networks_client.list_networks()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100230 seen_names = [n['name'] for n in seen_nets['networks']]
231 seen_ids = [n['id'] for n in seen_nets['networks']]
Yair Fried4d7efa62013-11-17 17:12:29 +0200232
Steve Heyman33735f22016-05-24 09:28:08 -0500233 self.assertIn(tenant.network['name'], seen_names)
234 self.assertIn(tenant.network['id'], seen_ids)
Yair Fried4d7efa62013-11-17 17:12:29 +0200235
Jordan Pittier64e6b442017-02-20 19:29:02 +0100236 seen_subnets = [
237 (n['id'], n['cidr'], n['network_id']) for n in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800238 self.os_admin.subnets_client.list_subnets()['subnets']
Jordan Pittier64e6b442017-02-20 19:29:02 +0100239 ]
Steve Heyman33735f22016-05-24 09:28:08 -0500240 mysubnet = (tenant.subnet['id'], tenant.subnet['cidr'],
241 tenant.network['id'])
Yair Fried4d7efa62013-11-17 17:12:29 +0200242 self.assertIn(mysubnet, seen_subnets)
243
jeremy.zhang5870ff12017-05-25 11:24:23 +0800244 seen_routers = self.os_admin.routers_client.list_routers()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100245 seen_router_ids = [n['id'] for n in seen_routers['routers']]
246 seen_router_names = [n['name'] for n in seen_routers['routers']]
Yair Fried4d7efa62013-11-17 17:12:29 +0200247
Steve Heyman33735f22016-05-24 09:28:08 -0500248 self.assertIn(tenant.router['name'], seen_router_names)
249 self.assertIn(tenant.router['id'], seen_router_ids)
Yair Fried4d7efa62013-11-17 17:12:29 +0200250
Steve Heyman33735f22016-05-24 09:28:08 -0500251 myport = (tenant.router['id'], tenant.subnet['id'])
Kevin Benton8801e362017-02-12 19:17:55 -0800252 router_ports = [
253 (i['device_id'], f['subnet_id'])
jeremy.zhang5870ff12017-05-25 11:24:23 +0800254 for i in self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100255 device_id=tenant.router['id'])['ports']
Kevin Benton8801e362017-02-12 19:17:55 -0800256 if net_info.is_router_interface_port(i)
Jordan Pittier64e6b442017-02-20 19:29:02 +0100257 for f in i['fixed_ips']
258 ]
Yair Fried4d7efa62013-11-17 17:12:29 +0200259
260 self.assertIn(myport, router_ports)
261
Markus Zoeller156b5da2016-07-11 18:10:31 +0200262 def _create_server(self, name, tenant, security_groups, **kwargs):
Yair Friedca5cfb52016-01-04 15:41:55 +0200263 """Creates a server and assigns it to security group.
264
265 If multi-host is enabled, Ensures servers are created on different
266 compute nodes, by storing created servers' ids and uses different_host
267 as scheduler_hints on creation.
268 Validates servers are created as requested, using admin client.
269 """
Ken'ichi Ohmichi1b3461e2014-12-02 03:41:07 +0000270 security_groups_names = [{'name': s['name']} for s in security_groups]
Yair Friedca5cfb52016-01-04 15:41:55 +0200271 if self.multi_node:
272 kwargs["scheduler_hints"] = {'different_host': self.servers}
Ken'ichi Ohmichif2d436e2015-09-03 01:13:16 +0000273 server = self.create_server(
274 name=name,
Steve Heyman33735f22016-05-24 09:28:08 -0500275 networks=[{'uuid': tenant.network["id"]}],
lanoux5fc14522015-09-21 08:17:35 +0000276 key_name=tenant.keypair['name'],
277 security_groups=security_groups_names,
Yair Friedca5cfb52016-01-04 15:41:55 +0200278 clients=tenant.manager,
279 **kwargs)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200280 if 'security_groups' in server:
281 self.assertEqual(
282 sorted([s['name'] for s in security_groups]),
283 sorted([s['name'] for s in server['security_groups']]))
Yair Friedca5cfb52016-01-04 15:41:55 +0200284
285 # Verify servers are on different compute nodes
286 if self.multi_node:
zhufl7bc916d2018-08-22 14:47:39 +0800287 new_host = self.get_host_for_server(server["id"])
288 host_list = [self.get_host_for_server(s) for s in self.servers]
Yair Friedca5cfb52016-01-04 15:41:55 +0200289 self.assertNotIn(new_host, host_list,
290 message="Failed to boot servers on different "
291 "Compute nodes.")
292
293 self.servers.append(server["id"])
294
Claudiu Belufaa98912014-09-01 16:50:28 +0300295 return server
Yair Fried4d7efa62013-11-17 17:12:29 +0200296
297 def _create_tenant_servers(self, tenant, num=1):
298 for i in range(num):
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000299 name = 'server-{tenant}-gen-{num}'.format(
Andrea Frittoli86ad28d2014-03-20 10:09:12 +0000300 tenant=tenant.creds.tenant_name,
Yair Fried4d7efa62013-11-17 17:12:29 +0200301 num=i
302 )
303 name = data_utils.rand_name(name)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200304 server = self._create_server(name, tenant,
305 [tenant.security_groups['default']])
Yair Fried4d7efa62013-11-17 17:12:29 +0200306 tenant.servers.append(server)
307
308 def _set_access_point(self, tenant):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000309 # creates a server in a secgroup with rule allowing external ssh
Sean Dagueed6e5862016-04-04 10:49:13 -0400310 # in order to access project internal network
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000311 # workaround ip namespace
Yair Frieddb6c9e92014-08-06 08:53:13 +0300312 secgroups = tenant.security_groups.values()
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000313 name = 'server-{tenant}-access_point'.format(
Andrea Frittoli86ad28d2014-03-20 10:09:12 +0000314 tenant=tenant.creds.tenant_name)
Yair Fried4d7efa62013-11-17 17:12:29 +0200315 name = data_utils.rand_name(name)
316 server = self._create_server(name, tenant,
317 security_groups=secgroups)
Yair Fried4d7efa62013-11-17 17:12:29 +0200318 tenant.access_point = server
Yair Frieddb6c9e92014-08-06 08:53:13 +0300319 self._assign_floating_ips(tenant, server)
Yair Fried4d7efa62013-11-17 17:12:29 +0200320
Yair Frieddb6c9e92014-08-06 08:53:13 +0300321 def _assign_floating_ips(self, tenant, server):
Matthew Treinish6c072292014-01-29 19:15:52 +0000322 public_network_id = CONF.network.public_network_id
Yair Friedae0e73d2014-11-24 11:56:26 +0200323 floating_ip = self.create_floating_ip(
Yair Frieddb6c9e92014-08-06 08:53:13 +0300324 server, public_network_id,
John Warrenfbf2a892015-11-17 12:36:14 -0500325 client=tenant.manager.floating_ips_client)
Yair Frieddb6c9e92014-08-06 08:53:13 +0300326 self.floating_ips.setdefault(server['id'], floating_ip)
Yair Fried4d7efa62013-11-17 17:12:29 +0200327
Markus Zoeller156b5da2016-07-11 18:10:31 +0200328 def _create_tenant_network(self, tenant, port_security_enabled=True):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300329 network, subnet, router = self.create_networks(
John Warren3961acd2015-10-02 14:38:53 -0400330 networks_client=tenant.manager.networks_client,
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000331 routers_client=tenant.manager.routers_client,
Markus Zoeller156b5da2016-07-11 18:10:31 +0200332 subnets_client=tenant.manager.subnets_client,
333 port_security_enabled=port_security_enabled)
Yair Friedbf2e2c42014-01-28 12:06:38 +0200334 tenant.set_network(network, subnet, router)
Yair Fried4d7efa62013-11-17 17:12:29 +0200335
Yair Fried4d7efa62013-11-17 17:12:29 +0200336 def _deploy_tenant(self, tenant_or_id):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000337 """creates:
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000338
Yair Fried4d7efa62013-11-17 17:12:29 +0200339 network
340 subnet
341 router (if public not defined)
342 access security group
343 access-point server
Yair Fried4d7efa62013-11-17 17:12:29 +0200344 """
345 if not isinstance(tenant_or_id, self.TenantProperties):
346 tenant = self.tenants[tenant_or_id]
Yair Fried4d7efa62013-11-17 17:12:29 +0200347 else:
348 tenant = tenant_or_id
Yair Frieddb6c9e92014-08-06 08:53:13 +0300349 self._create_tenant_keypairs(tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200350 self._create_tenant_network(tenant)
351 self._create_tenant_security_groups(tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200352 self._set_access_point(tenant)
353
354 def _get_server_ip(self, server, floating=False):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000355 """returns the ip (floating/internal) of a server"""
Yair Fried4d7efa62013-11-17 17:12:29 +0200356 if floating:
Steve Heyman33735f22016-05-24 09:28:08 -0500357 server_ip = self.floating_ips[server['id']]['floating_ip_address']
Yair Fried4d7efa62013-11-17 17:12:29 +0200358 else:
armando-migliacciod03f2642014-02-21 19:55:50 -0800359 server_ip = None
Steve Heyman33735f22016-05-24 09:28:08 -0500360 network_name = self.tenants[server['tenant_id']].network['name']
Yair Frieddb6c9e92014-08-06 08:53:13 +0300361 if network_name in server['addresses']:
362 server_ip = server['addresses'][network_name][0]['addr']
armando-migliacciod03f2642014-02-21 19:55:50 -0800363 return server_ip
Yair Fried4d7efa62013-11-17 17:12:29 +0200364
365 def _connect_to_access_point(self, tenant):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000366 """create ssh connection to tenant access point"""
Yair Fried4d7efa62013-11-17 17:12:29 +0200367 access_point_ssh = \
Steve Heyman33735f22016-05-24 09:28:08 -0500368 self.floating_ips[tenant.access_point['id']]['floating_ip_address']
Yair Frieddb6c9e92014-08-06 08:53:13 +0300369 private_key = tenant.keypair['private_key']
Jordan Pittierbbb17122016-01-26 17:10:55 +0100370 access_point_ssh = self.get_remote_client(
Slawek Kaplonskiab7d7902018-08-04 11:50:31 +0200371 access_point_ssh, private_key=private_key,
372 server=tenant.access_point)
Yair Fried4d7efa62013-11-17 17:12:29 +0200373 return access_point_ssh
374
Yair Fried4d7efa62013-11-17 17:12:29 +0200375 def _test_in_tenant_block(self, tenant):
376 access_point_ssh = self._connect_to_access_point(tenant)
377 for server in tenant.servers:
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900378 self.check_remote_connectivity(source=access_point_ssh,
379 dest=self._get_server_ip(server),
380 should_succeed=False)
Yair Fried4d7efa62013-11-17 17:12:29 +0200381
382 def _test_in_tenant_allow(self, tenant):
383 ruleset = dict(
384 protocol='icmp',
Steve Heyman33735f22016-05-24 09:28:08 -0500385 remote_group_id=tenant.security_groups['default']['id'],
Yair Fried4d7efa62013-11-17 17:12:29 +0200386 direction='ingress'
387 )
Matthew Treinishb7144eb2013-12-13 22:57:35 +0000388 self._create_security_group_rule(
Yair Fried4d7efa62013-11-17 17:12:29 +0200389 secgroup=tenant.security_groups['default'],
Yair Friedca5cfb52016-01-04 15:41:55 +0200390 security_groups_client=tenant.manager.security_groups_client,
Yair Fried4d7efa62013-11-17 17:12:29 +0200391 **ruleset
392 )
393 access_point_ssh = self._connect_to_access_point(tenant)
394 for server in tenant.servers:
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900395 self.check_remote_connectivity(source=access_point_ssh,
396 dest=self._get_server_ip(server))
Yair Fried4d7efa62013-11-17 17:12:29 +0200397
Claudiu Belu33c3e602014-08-28 16:38:01 +0300398 def _test_cross_tenant_block(self, source_tenant, dest_tenant, ruleset):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000399 # if public router isn't defined, then dest_tenant access is via
400 # floating-ip
Claudiu Belu33c3e602014-08-28 16:38:01 +0300401 protocol = ruleset['protocol']
Yair Fried4d7efa62013-11-17 17:12:29 +0200402 access_point_ssh = self._connect_to_access_point(source_tenant)
403 ip = self._get_server_ip(dest_tenant.access_point,
404 floating=self.floating_ip_access)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900405 self.check_remote_connectivity(source=access_point_ssh, dest=ip,
Claudiu Belu33c3e602014-08-28 16:38:01 +0300406 should_succeed=False, protocol=protocol)
Yair Fried4d7efa62013-11-17 17:12:29 +0200407
Claudiu Belu33c3e602014-08-28 16:38:01 +0300408 def _test_cross_tenant_allow(self, source_tenant, dest_tenant, ruleset):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000409 """check for each direction:
410
Yair Fried4d7efa62013-11-17 17:12:29 +0200411 creating rule for tenant incoming traffic enables only 1way traffic
Yair Friedbf2e2c42014-01-28 12:06:38 +0200412 """
Claudiu Belu33c3e602014-08-28 16:38:01 +0300413 protocol = ruleset['protocol']
John Warren456d9ae2016-01-12 15:36:33 -0500414 sec_group_rules_client = (
415 dest_tenant.manager.security_group_rules_client)
Matthew Treinishb7144eb2013-12-13 22:57:35 +0000416 self._create_security_group_rule(
Yair Fried4d7efa62013-11-17 17:12:29 +0200417 secgroup=dest_tenant.security_groups['default'],
John Warren456d9ae2016-01-12 15:36:33 -0500418 sec_group_rules_client=sec_group_rules_client,
Yair Fried4d7efa62013-11-17 17:12:29 +0200419 **ruleset
420 )
Yair Friedbf2e2c42014-01-28 12:06:38 +0200421 access_point_ssh = self._connect_to_access_point(source_tenant)
422 ip = self._get_server_ip(dest_tenant.access_point,
423 floating=self.floating_ip_access)
Claudiu Belu33c3e602014-08-28 16:38:01 +0300424 self.check_remote_connectivity(access_point_ssh, ip, protocol=protocol)
Yair Fried4d7efa62013-11-17 17:12:29 +0200425
Yair Friedbf2e2c42014-01-28 12:06:38 +0200426 # test that reverse traffic is still blocked
Claudiu Belu33c3e602014-08-28 16:38:01 +0300427 self._test_cross_tenant_block(dest_tenant, source_tenant, ruleset)
Yair Fried4d7efa62013-11-17 17:12:29 +0200428
Yair Friedbf2e2c42014-01-28 12:06:38 +0200429 # allow reverse traffic and check
John Warren456d9ae2016-01-12 15:36:33 -0500430 sec_group_rules_client = (
431 source_tenant.manager.security_group_rules_client)
Matthew Treinishb7144eb2013-12-13 22:57:35 +0000432 self._create_security_group_rule(
Yair Friedbf2e2c42014-01-28 12:06:38 +0200433 secgroup=source_tenant.security_groups['default'],
John Warren456d9ae2016-01-12 15:36:33 -0500434 sec_group_rules_client=sec_group_rules_client,
Yair Friedbf2e2c42014-01-28 12:06:38 +0200435 **ruleset
436 )
Yair Fried4d7efa62013-11-17 17:12:29 +0200437
Yair Friedbf2e2c42014-01-28 12:06:38 +0200438 access_point_ssh_2 = self._connect_to_access_point(dest_tenant)
439 ip = self._get_server_ip(source_tenant.access_point,
440 floating=self.floating_ip_access)
Claudiu Belu33c3e602014-08-28 16:38:01 +0300441 self.check_remote_connectivity(access_point_ssh_2, ip,
442 protocol=protocol)
Yair Fried4d7efa62013-11-17 17:12:29 +0200443
444 def _verify_mac_addr(self, tenant):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000445 """Verify that VM has the same ip, mac as listed in port"""
446
Yair Fried4d7efa62013-11-17 17:12:29 +0200447 access_point_ssh = self._connect_to_access_point(tenant)
448 mac_addr = access_point_ssh.get_mac_address()
449 mac_addr = mac_addr.strip().lower()
Henry Gessau78ab4b02014-03-31 15:10:13 -0400450 # Get the fixed_ips and mac_address fields of all ports. Select
451 # only those two columns to reduce the size of the response.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800452 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100453 fields=['fixed_ips', 'mac_address'])['ports']
Yair Fried4d7efa62013-11-17 17:12:29 +0200454 port_detail_list = [
455 (port['fixed_ips'][0]['subnet_id'],
456 port['fixed_ips'][0]['ip_address'],
Henry Gessau78ab4b02014-03-31 15:10:13 -0400457 port['mac_address'].lower())
458 for port in port_list if port['fixed_ips']
Yair Fried4d7efa62013-11-17 17:12:29 +0200459 ]
460 server_ip = self._get_server_ip(tenant.access_point)
Steve Heyman33735f22016-05-24 09:28:08 -0500461 subnet_id = tenant.subnet['id']
Yair Fried4d7efa62013-11-17 17:12:29 +0200462 self.assertIn((subnet_id, server_ip, mac_addr), port_detail_list)
463
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700464 def _log_console_output_for_all_tenants(self):
465 for tenant in self.tenants.values():
466 client = tenant.manager.servers_client
Soniya Vyas1b0cddc2021-01-29 17:28:19 +0530467 self.log_console_output(servers=tenant.servers, client=client)
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700468 if tenant.access_point is not None:
Soniya Vyas1b0cddc2021-01-29 17:28:19 +0530469 self.log_console_output(
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700470 servers=[tenant.access_point], client=client)
471
Claudiu Belu33c3e602014-08-28 16:38:01 +0300472 def _create_protocol_ruleset(self, protocol, port=80):
473 if protocol == 'icmp':
474 ruleset = dict(protocol='icmp',
475 direction='ingress')
476 else:
477 ruleset = dict(protocol=protocol,
478 port_range_min=port,
479 port_range_max=port,
480 direction='ingress')
481 return ruleset
482
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800483 @decorators.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
Andrea Frittolicd368412017-08-14 21:37:56 +0100484 @utils.services('compute', 'network')
Yair Fried4d7efa62013-11-17 17:12:29 +0200485 def test_cross_tenant_traffic(self):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100486 if not self.credentials_provider.is_multi_tenant():
Yair Fried79b0a912014-10-20 11:15:37 +0300487 raise self.skipException("No secondary tenant defined")
Nachi Ueno26b4c972014-01-17 06:15:13 -0800488 try:
Sean Dagueed6e5862016-04-04 10:49:13 -0400489 # deploy new project
Yair Friedbf2e2c42014-01-28 12:06:38 +0200490 self._deploy_tenant(self.alt_tenant)
491 self._verify_network_details(self.alt_tenant)
492 self._verify_mac_addr(self.alt_tenant)
Yair Fried4d7efa62013-11-17 17:12:29 +0200493
Nachi Ueno26b4c972014-01-17 06:15:13 -0800494 # cross tenant check
Yair Friedbf2e2c42014-01-28 12:06:38 +0200495 source_tenant = self.primary_tenant
Nachi Ueno26b4c972014-01-17 06:15:13 -0800496 dest_tenant = self.alt_tenant
Claudiu Belu33c3e602014-08-28 16:38:01 +0300497
498 protocol = CONF.scenario.protocol
499 LOG.debug("Testing cross tenant traffic for %s protocol",
500 protocol)
501 if protocol in ['udp', 'tcp']:
502 for tenant in [source_tenant, dest_tenant]:
503 access_point = self._connect_to_access_point(tenant)
504 access_point.nc_listen_host(protocol=protocol)
505
506 ruleset = self._create_protocol_ruleset(protocol)
507 self._test_cross_tenant_block(source_tenant, dest_tenant, ruleset)
508 self._test_cross_tenant_allow(source_tenant, dest_tenant, ruleset)
Nachi Ueno26b4c972014-01-17 06:15:13 -0800509 except Exception:
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700510 self._log_console_output_for_all_tenants()
Yair Friedbf2e2c42014-01-28 12:06:38 +0200511 raise
512
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800513 @decorators.idempotent_id('63163892-bbf6-4249-aa12-d5ea1f8f421b')
Andrea Frittolicd368412017-08-14 21:37:56 +0100514 @utils.services('compute', 'network')
Yair Friedbf2e2c42014-01-28 12:06:38 +0200515 def test_in_tenant_traffic(self):
516 try:
517 self._create_tenant_servers(self.primary_tenant, num=1)
518
519 # in-tenant check
520 self._test_in_tenant_block(self.primary_tenant)
521 self._test_in_tenant_allow(self.primary_tenant)
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800522 except Exception:
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700523 self._log_console_output_for_all_tenants()
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800524 raise
Yair Friedbf2e2c42014-01-28 12:06:38 +0200525
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800526 @decorators.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200527 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100528 @utils.services('compute', 'network')
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800529 def test_port_update_new_security_group(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000530 """Verifies the traffic after updating the vm port
531
532 With new security group having appropriate rule.
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800533 """
534 new_tenant = self.primary_tenant
535
536 # Create empty security group and add icmp rule in it
537 new_sg = self._create_empty_security_group(
538 namestart='secgroup_new-',
Rodolfo Alonso Hernandezc1449d42020-02-15 13:24:28 +0000539 project_id=new_tenant.creds.project_id,
John Warrenf9606e92015-12-10 12:12:42 -0500540 client=new_tenant.manager.security_groups_client)
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800541 icmp_rule = dict(
542 protocol='icmp',
543 direction='ingress',
544 )
John Warren456d9ae2016-01-12 15:36:33 -0500545 sec_group_rules_client = new_tenant.manager.security_group_rules_client
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800546 self._create_security_group_rule(
547 secgroup=new_sg,
John Warren456d9ae2016-01-12 15:36:33 -0500548 sec_group_rules_client=sec_group_rules_client,
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800549 **icmp_rule)
550 new_tenant.security_groups.update(new_sg=new_sg)
551
552 # Create server with default security group
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000553 name = 'server-{tenant}-gen-1'.format(
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800554 tenant=new_tenant.creds.tenant_name
555 )
556 name = data_utils.rand_name(name)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200557 server = self._create_server(name, new_tenant,
558 [new_tenant.security_groups['default']])
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800559
560 # Check connectivity failure with default security group
561 try:
562 access_point_ssh = self._connect_to_access_point(new_tenant)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900563 self.check_remote_connectivity(source=access_point_ssh,
564 dest=self._get_server_ip(server),
565 should_succeed=False)
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800566 server_id = server['id']
jeremy.zhang5870ff12017-05-25 11:24:23 +0800567 port_id = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100568 device_id=server_id)['ports'][0]['id']
Rajkumar Thiyagarajand9e964a2014-12-17 01:55:52 -0800569
570 # update port with new security group and check connectivity
John Warren49c0fe52015-10-22 12:35:54 -0400571 self.ports_client.update_port(port_id, security_groups=[
Steve Heyman33735f22016-05-24 09:28:08 -0500572 new_tenant.security_groups['new_sg']['id']])
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900573 self.check_remote_connectivity(
574 source=access_point_ssh,
575 dest=self._get_server_ip(server))
Yair Friedbf2e2c42014-01-28 12:06:38 +0200576 except Exception:
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700577 self._log_console_output_for_all_tenants()
Nachi Ueno26b4c972014-01-17 06:15:13 -0800578 raise
prdsilva8b733ad2014-12-09 02:54:49 -0800579
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800580 @decorators.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200581 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100582 @utils.services('compute', 'network')
prdsilva8b733ad2014-12-09 02:54:49 -0800583 def test_multiple_security_groups(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000584 """Verify multiple security groups and checks that rules
585
prdsilva8b733ad2014-12-09 02:54:49 -0800586 provided in the both the groups is applied onto VM
587 """
588 tenant = self.primary_tenant
589 ip = self._get_server_ip(tenant.access_point,
590 floating=self.floating_ip_access)
lanoux283273b2015-12-04 03:01:54 -0800591 ssh_login = CONF.validation.image_ssh_user
prdsilva8b733ad2014-12-09 02:54:49 -0800592 private_key = tenant.keypair['private_key']
593 self.check_vm_connectivity(ip,
594 should_connect=False)
595 ruleset = dict(
596 protocol='icmp',
597 direction='ingress'
598 )
599 self._create_security_group_rule(
600 secgroup=tenant.security_groups['default'],
601 **ruleset
602 )
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000603 # NOTE: Vm now has 2 security groups one with ssh rule(
604 # already added in setUp() method),and other with icmp rule
605 # (added in the above step).The check_vm_connectivity tests
606 # -that vm ping test is successful
607 # -ssh to vm is successful
prdsilva8b733ad2014-12-09 02:54:49 -0800608 self.check_vm_connectivity(ip,
609 username=ssh_login,
610 private_key=private_key,
611 should_connect=True)
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900612
Jordan Pittier3b46d272017-04-12 16:17:28 +0200613 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100614 @utils.requires_ext(service='network', extension='port-security')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800615 @decorators.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
Andrea Frittolicd368412017-08-14 21:37:56 +0100616 @utils.services('compute', 'network')
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900617 def test_port_security_disable_security_group(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000618 """Verify the default security group rules is disabled."""
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900619 new_tenant = self.primary_tenant
620
621 # Create server
622 name = 'server-{tenant}-gen-1'.format(
623 tenant=new_tenant.creds.tenant_name
624 )
625 name = data_utils.rand_name(name)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200626 server = self._create_server(name, new_tenant,
627 [new_tenant.security_groups['default']])
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900628
629 access_point_ssh = self._connect_to_access_point(new_tenant)
630 server_id = server['id']
jeremy.zhang5870ff12017-05-25 11:24:23 +0800631 port_id = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100632 device_id=server_id)['ports'][0]['id']
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900633
634 # Flip the port's port security and check connectivity
635 try:
John Warren49c0fe52015-10-22 12:35:54 -0400636 self.ports_client.update_port(port_id,
637 port_security_enabled=True,
638 security_groups=[])
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900639 self.check_remote_connectivity(source=access_point_ssh,
640 dest=self._get_server_ip(server),
641 should_succeed=False)
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900642
John Warren49c0fe52015-10-22 12:35:54 -0400643 self.ports_client.update_port(port_id,
644 port_security_enabled=False,
645 security_groups=[])
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900646 self.check_remote_connectivity(
647 source=access_point_ssh,
648 dest=self._get_server_ip(server))
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900649 except Exception:
Ihar Hrachyshkaa9dca2b2017-04-04 14:17:11 -0700650 self._log_console_output_for_all_tenants()
YAMAMOTO Takashi51e04082015-09-08 18:44:23 +0900651 raise
Markus Zoeller156b5da2016-07-11 18:10:31 +0200652
Jordan Pittier3b46d272017-04-12 16:17:28 +0200653 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100654 @utils.requires_ext(service='network', extension='port-security')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800655 @decorators.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
Matt Riedemann039b2fe2016-09-15 16:12:24 -0400656 # TODO(mriedem): We shouldn't actually need to check this since neutron
657 # disables the port_security extension by default, but the problem is nova
658 # assumes port_security_enabled=True if it's not set on the network
659 # resource, which will mean nova may attempt to apply a security group on
660 # a port on that network which would fail. This is really a bug in nova.
661 @testtools.skipUnless(
662 CONF.network_feature_enabled.port_security,
663 'Port security must be enabled.')
Andrea Frittolicd368412017-08-14 21:37:56 +0100664 @utils.services('compute', 'network')
Markus Zoeller156b5da2016-07-11 18:10:31 +0200665 def test_boot_into_disabled_port_security_network_without_secgroup(self):
666 tenant = self.primary_tenant
667 self._create_tenant_network(tenant, port_security_enabled=False)
668 self.assertFalse(tenant.network['port_security_enabled'])
669 name = data_utils.rand_name('server-smoke')
670 sec_groups = []
671 server = self._create_server(name, tenant, sec_groups)
672 server_id = server['id']
jeremy.zhang5870ff12017-05-25 11:24:23 +0800673 ports = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100674 device_id=server_id)['ports']
Markus Zoeller156b5da2016-07-11 18:10:31 +0200675 self.assertEqual(1, len(ports))
676 for port in ports:
677 self.assertEmpty(port['security_groups'],
678 "Neutron shouldn't even use it's default sec "
679 "group.")