Skip to content

Commit daadcd7

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Support IPv6 addresses better"
2 parents 1bad2cb + 969e6ab commit daadcd7

5 files changed

Lines changed: 79 additions & 15 deletions

File tree

doc/source/cli/command-objects/security-group-rule.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ Create a new security group rule
2727
2828
.. option:: --remote-ip <ip-address>
2929
30-
Remote IP address block
31-
(may use CIDR notation; default for IPv4 rule: 0.0.0.0/0)
30+
Remote IP address block (may use CIDR notation;
31+
default for IPv4 rule: 0.0.0.0/0,
32+
default for IPv6 rule: ::/0)
3233
3334
.. option:: --remote-group <group>
3435
@@ -134,6 +135,7 @@ List security group rules
134135
openstack security group rule list
135136
[--all-projects]
136137
[--protocol <protocol>]
138+
[--ethertype <ethertype>]
137139
[--ingress | --egress]
138140
[--long]
139141
[<group>]
@@ -151,7 +153,6 @@ List security group rules
151153
152154
*Compute version 2 does not have additional fields to display.*
153155
154-
155156
.. option:: --protocol
156157
157158
List rules by the IP protocol (ah, dhcp, egp, esp, gre, icmp, igmp,
@@ -161,6 +162,12 @@ List security group rules
161162
162163
*Network version 2*
163164
165+
.. option:: --ethertype
166+
167+
List rules by the Ethertype (IPv4 or IPv6)
168+
169+
*Network version 2*
170+
164171
.. option:: --ingress
165172
166173
List rules applied to incoming network traffic

openstackclient/network/v2/security_group_rule.py

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ def _format_network_port_range(rule):
6262
return port_range
6363

6464

65+
def _format_remote_ip_prefix(rule):
66+
remote_ip_prefix = rule['remote_ip_prefix']
67+
if remote_ip_prefix is None:
68+
ethertype = rule['ether_type']
69+
if ethertype == 'IPv4':
70+
remote_ip_prefix = '0.0.0.0/0'
71+
elif ethertype == 'IPv6':
72+
remote_ip_prefix = '::/0'
73+
return remote_ip_prefix
74+
75+
6576
def _get_columns(item):
6677
column_map = {
6778
'tenant_id': 'project_id',
@@ -108,7 +119,8 @@ def update_parser_common(self, parser):
108119
"--remote-ip",
109120
metavar="<ip-address>",
110121
help=_("Remote IP address block (may use CIDR notation; "
111-
"default for IPv4 rule: 0.0.0.0/0)"),
122+
"default for IPv4 rule: 0.0.0.0/0, "
123+
"default for IPv6 rule: ::/0)"),
112124
)
113125
remote_group.add_argument(
114126
"--remote-group",
@@ -230,6 +242,14 @@ def _get_protocol(self, parsed_args, default_protocol='any'):
230242
protocol = None
231243
return protocol
232244

245+
def _get_ethertype(self, parsed_args, protocol):
246+
ethertype = 'IPv4'
247+
if parsed_args.ethertype is not None:
248+
ethertype = parsed_args.ethertype
249+
elif self._is_ipv6_protocol(protocol):
250+
ethertype = 'IPv6'
251+
return ethertype
252+
233253
def _is_ipv6_protocol(self, protocol):
234254
# NOTE(rtheis): Neutron has deprecated protocol icmpv6.
235255
# However, while the OSC CLI doesn't document the protocol,
@@ -264,12 +284,8 @@ def take_action_network(self, client, parsed_args):
264284

265285
# NOTE(rtheis): Use ethertype specified else default based
266286
# on IP protocol.
267-
if parsed_args.ethertype:
268-
attrs['ethertype'] = parsed_args.ethertype
269-
elif self._is_ipv6_protocol(attrs['protocol']):
270-
attrs['ethertype'] = 'IPv6'
271-
else:
272-
attrs['ethertype'] = 'IPv4'
287+
attrs['ethertype'] = self._get_ethertype(parsed_args,
288+
attrs['protocol'])
273289

274290
# NOTE(rtheis): Validate the port range and ICMP type and code.
275291
# It would be ideal if argparse could do this.
@@ -306,6 +322,8 @@ def take_action_network(self, client, parsed_args):
306322
attrs['remote_ip_prefix'] = parsed_args.remote_ip
307323
elif attrs['ethertype'] == 'IPv4':
308324
attrs['remote_ip_prefix'] = '0.0.0.0/0'
325+
elif attrs['ethertype'] == 'IPv6':
326+
attrs['remote_ip_prefix'] = '::/0'
309327
attrs['security_group_id'] = security_group_id
310328
if parsed_args.project is not None:
311329
identity_client = self.app.client_manager.identity
@@ -387,6 +405,7 @@ def _format_network_security_group_rule(self, rule):
387405
"""
388406
rule = rule.to_dict()
389407
rule['port_range'] = _format_network_port_range(rule)
408+
rule['remote_ip_prefix'] = _format_remote_ip_prefix(rule)
390409
return rule
391410

392411
def update_parser_common(self, parser):
@@ -418,6 +437,12 @@ def update_parser_network(self, parser):
418437
"udp, udplite, vrrp and integer representations [0-255] "
419438
"or any; default: any (all protocols))")
420439
)
440+
parser.add_argument(
441+
'--ethertype',
442+
metavar='<ethertype>',
443+
type=_convert_to_lowercase,
444+
help=_("List rules by the Ethertype (IPv4 or IPv6)")
445+
)
421446
direction_group = parser.add_mutually_exclusive_group()
422447
direction_group.add_argument(
423448
'--ingress',
@@ -458,11 +483,12 @@ def _get_column_headers(self, parsed_args):
458483
column_headers = (
459484
'ID',
460485
'IP Protocol',
486+
'Ethertype',
461487
'IP Range',
462488
'Port Range',
463489
)
464490
if parsed_args.long:
465-
column_headers = column_headers + ('Direction', 'Ethertype',)
491+
column_headers = column_headers + ('Direction',)
466492
column_headers = column_headers + ('Remote Security Group',)
467493
if parsed_args.group is None:
468494
column_headers = column_headers + ('Security Group',)
@@ -473,11 +499,12 @@ def take_action_network(self, client, parsed_args):
473499
columns = (
474500
'id',
475501
'protocol',
502+
'ether_type',
476503
'remote_ip_prefix',
477504
'port_range',
478505
)
479506
if parsed_args.long:
480-
columns = columns + ('direction', 'ether_type',)
507+
columns = columns + ('direction',)
481508
columns = columns + ('remote_group_id',)
482509

483510
# Get the security group rules using the requested query.
@@ -516,6 +543,7 @@ def take_action_compute(self, client, parsed_args):
516543
columns = (
517544
"ID",
518545
"IP Protocol",
546+
"Ethertype",
519547
"IP Range",
520548
"Port Range",
521549
"Remote Security Group",
@@ -564,6 +592,9 @@ def update_parser_common(self, parser):
564592
def take_action_network(self, client, parsed_args):
565593
obj = client.find_security_group_rule(parsed_args.rule,
566594
ignore_missing=False)
595+
# necessary for old rules that have None in this field
596+
if not obj['remote_ip_prefix']:
597+
obj['remote_ip_prefix'] = _format_remote_ip_prefix(obj)
567598
display_columns, columns = _get_columns(obj)
568599
data = utils.get_item_properties(obj, columns)
569600
return (display_columns, data)

openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,15 @@ class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
337337
_security_group_rule_tcp = \
338338
compute_fakes.FakeSecurityGroupRule.create_one_security_group_rule({
339339
'ip_protocol': 'tcp',
340+
'ethertype': 'IPv4',
340341
'from_port': 80,
341342
'to_port': 80,
342343
'group': {'name': _security_group['name']},
343344
})
344345
_security_group_rule_icmp = \
345346
compute_fakes.FakeSecurityGroupRule.create_one_security_group_rule({
346347
'ip_protocol': 'icmp',
348+
'ethertype': 'IPv4',
347349
'from_port': -1,
348350
'to_port': -1,
349351
'ip_range': {'cidr': '10.0.2.0/24'},
@@ -357,6 +359,7 @@ class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
357359
expected_columns_with_group = (
358360
'ID',
359361
'IP Protocol',
362+
'Ethertype',
360363
'IP Range',
361364
'Port Range',
362365
'Remote Security Group',
@@ -373,6 +376,7 @@ class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
373376
expected_rule_with_group = (
374377
rule['id'],
375378
rule['ip_protocol'],
379+
rule['ethertype'],
376380
rule['ip_range'],
377381
rule['port_range'],
378382
rule['remote_security_group'],

openstackclient/tests/unit/network/v2/test_security_group_rule_network.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ def test_create_network_options(self):
388388
'port_range_min': 443,
389389
'protocol': '6',
390390
'remote_group_id': None,
391-
'remote_ip_prefix': None,
391+
'remote_ip_prefix': '::/0',
392392
})
393393
arglist = [
394394
'--dst-port', str(self._security_group_rule.port_range_min),
@@ -419,6 +419,7 @@ def test_create_network_options(self):
419419
'port_range_max': self._security_group_rule.port_range_max,
420420
'port_range_min': self._security_group_rule.port_range_min,
421421
'protocol': self._security_group_rule.protocol,
422+
'remote_ip_prefix': self._security_group_rule.remote_ip_prefix,
422423
'security_group_id': self._security_group.id,
423424
'tenant_id': self.project.id,
424425
})
@@ -664,6 +665,7 @@ def test_create_ipv6_icmp_type_code(self):
664665
'port_range_min': 139,
665666
'port_range_max': 2,
666667
'protocol': 'ipv6-icmp',
668+
'remote_ip_prefix': '::/0',
667669
})
668670
arglist = [
669671
'--icmp-type', str(self._security_group_rule.port_range_min),
@@ -688,6 +690,7 @@ def test_create_ipv6_icmp_type_code(self):
688690
'port_range_min': self._security_group_rule.port_range_min,
689691
'port_range_max': self._security_group_rule.port_range_max,
690692
'protocol': self._security_group_rule.protocol,
693+
'remote_ip_prefix': self._security_group_rule.remote_ip_prefix,
691694
'security_group_id': self._security_group.id,
692695
})
693696
self.assertEqual(self.expected_columns, columns)
@@ -698,6 +701,7 @@ def test_create_icmpv6_type(self):
698701
'ether_type': 'IPv6',
699702
'port_range_min': 139,
700703
'protocol': 'icmpv6',
704+
'remote_ip_prefix': '::/0',
701705
})
702706
arglist = [
703707
'--icmp-type', str(self._security_group_rule.port_range_min),
@@ -720,6 +724,7 @@ def test_create_icmpv6_type(self):
720724
'ethertype': self._security_group_rule.ether_type,
721725
'port_range_min': self._security_group_rule.port_range_min,
722726
'protocol': self._security_group_rule.protocol,
727+
'remote_ip_prefix': self._security_group_rule.remote_ip_prefix,
723728
'security_group_id': self._security_group.id,
724729
})
725730
self.assertEqual(self.expected_columns, columns)
@@ -868,15 +873,16 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
868873
expected_columns_with_group_and_long = (
869874
'ID',
870875
'IP Protocol',
876+
'Ethertype',
871877
'IP Range',
872878
'Port Range',
873879
'Direction',
874-
'Ethertype',
875880
'Remote Security Group',
876881
)
877882
expected_columns_no_group = (
878883
'ID',
879884
'IP Protocol',
885+
'Ethertype',
880886
'IP Range',
881887
'Port Range',
882888
'Remote Security Group',
@@ -889,16 +895,17 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
889895
expected_data_with_group_and_long.append((
890896
_security_group_rule.id,
891897
_security_group_rule.protocol,
898+
_security_group_rule.ether_type,
892899
_security_group_rule.remote_ip_prefix,
893900
security_group_rule._format_network_port_range(
894901
_security_group_rule),
895902
_security_group_rule.direction,
896-
_security_group_rule.ether_type,
897903
_security_group_rule.remote_group_id,
898904
))
899905
expected_data_no_group.append((
900906
_security_group_rule.id,
901907
_security_group_rule.protocol,
908+
_security_group_rule.ether_type,
902909
_security_group_rule.remote_ip_prefix,
903910
security_group_rule._format_network_port_range(
904911
_security_group_rule),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
features:
3+
- |
4+
Security group rules can now be filtered by Ethertype in
5+
``security group rule list`` using ``--ethertype`` with either
6+
``ipv4`` or ``ipv6`` as an argument.
7+
upgrade:
8+
- |
9+
Security group rule listings now have the ``Ethertype`` field displayed
10+
by default to more easily differentiate between IPv4 and IPv6 rules.
11+
In addition, the ``IP Range`` field of a security group will be
12+
changed to ``0.0.0.0/0`` for IPv4 and ``::/0`` for IPv6 if no
13+
value is returned for the address, based on the Ethertype field of
14+
the rule. For further information see
15+
[Bug `1735575 <https://bugs.launchpad.net/bugs/1735575>`_]

0 commit comments

Comments
 (0)