Skip to content

Commit ef68f23

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Add network options to security group rule create"
2 parents e130518 + 3a3f33b commit ef68f23

5 files changed

Lines changed: 127 additions & 15 deletions

File tree

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Create a new security group rule
1616
[--proto <proto>]
1717
[--src-ip <ip-address> | --src-group <group>]
1818
[--dst-port <port-range>]
19+
[--ingress | --egress]
20+
[--ethertype <ethertype>]
1921
<group>
2022
2123
.. option:: --proto <proto>
@@ -24,7 +26,8 @@ Create a new security group rule
2426

2527
.. option:: --src-ip <ip-address>
2628

27-
Source IP address block (may use CIDR notation; default: 0.0.0.0/0)
29+
Source IP address block
30+
(may use CIDR notation; default for IPv4 rule: 0.0.0.0/0)
2831

2932
.. option:: --src-group <group>
3033

@@ -35,6 +38,24 @@ Create a new security group rule
3538
Destination port, may be a single port or port range: 137:139
3639
(only required for IP protocols tcp and udp)
3740

41+
.. option:: --ingress
42+
43+
Rule applies to incoming network traffic (default)
44+
45+
*Network version 2 only*
46+
47+
.. option:: --egress
48+
49+
Rule applies to outgoing network traffic
50+
51+
*Network version 2 only*
52+
53+
.. option:: --ethertype <ethertype>
54+
55+
Ethertype of network traffic (IPv4, IPv6; default: IPv4)
56+
57+
*Network version 2 only*
58+
3859
.. describe:: <group>
3960

4061
Create rule in this security group (name or ID)

functional/tests/network/v2/test_security_group_rule.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def setUpClass(cls):
3838
raw_output = cls.openstack('security group rule create ' +
3939
cls.SECURITY_GROUP_NAME +
4040
' --proto tcp --dst-port 80:80' +
41+
' --ingress --ethertype IPv4' +
4142
opts)
4243
cls.SECURITY_GROUP_RULE_ID = raw_output.strip('\n')
4344

openstackclient/network/v2/security_group_rule.py

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ def update_parser_common(self, parser):
6868
help='Create rule in this security group (name or ID)',
6969
)
7070
# TODO(rtheis): Add support for additional protocols for network.
71-
# Until then, continue enforcing the compute choices.
71+
# Until then, continue enforcing the compute choices. When additional
72+
# protocols are added, the default ethertype must be determined
73+
# based on the protocol.
7274
parser.add_argument(
7375
"--proto",
7476
metavar="<proto>",
@@ -81,9 +83,8 @@ def update_parser_common(self, parser):
8183
source_group.add_argument(
8284
"--src-ip",
8385
metavar="<ip-address>",
84-
default="0.0.0.0/0",
85-
help="Source IP address block (may use CIDR notation; default: "
86-
"0.0.0.0/0)",
86+
help="Source IP address block (may use CIDR notation; "
87+
"default for IPv4 rule: 0.0.0.0/0)",
8788
)
8889
source_group.add_argument(
8990
"--src-group",
@@ -100,6 +101,27 @@ def update_parser_common(self, parser):
100101
)
101102
return parser
102103

104+
def update_parser_network(self, parser):
105+
direction_group = parser.add_mutually_exclusive_group()
106+
direction_group.add_argument(
107+
'--ingress',
108+
action='store_true',
109+
help='Rule applies to incoming network traffic (default)',
110+
)
111+
direction_group.add_argument(
112+
'--egress',
113+
action='store_true',
114+
help='Rule applies to outgoing network traffic',
115+
)
116+
parser.add_argument(
117+
'--ethertype',
118+
metavar='<ethertype>',
119+
choices=['IPv4', 'IPv6'],
120+
help='Ethertype of network traffic '
121+
'(IPv4, IPv6; default: IPv4)',
122+
)
123+
return parser
124+
103125
def take_action_network(self, client, parsed_args):
104126
# Get the security group ID to hold the rule.
105127
security_group_id = client.find_security_group(
@@ -109,12 +131,18 @@ def take_action_network(self, client, parsed_args):
109131

110132
# Build the create attributes.
111133
attrs = {}
112-
# TODO(rtheis): Add --direction option. Until then, continue
113-
# with the default of 'ingress'.
114-
attrs['direction'] = 'ingress'
115-
# TODO(rtheis): Add --ethertype option. Until then, continue
116-
# with the default of 'IPv4'
117-
attrs['ethertype'] = 'IPv4'
134+
# NOTE(rtheis): A direction must be specified and ingress
135+
# is the default.
136+
if parsed_args.ingress or not parsed_args.egress:
137+
attrs['direction'] = 'ingress'
138+
if parsed_args.egress:
139+
attrs['direction'] = 'egress'
140+
if parsed_args.ethertype:
141+
attrs['ethertype'] = parsed_args.ethertype
142+
else:
143+
# NOTE(rtheis): Default based on protocol is IPv4 for now.
144+
# Once IPv6 protocols are added, this will need to be updated.
145+
attrs['ethertype'] = 'IPv4'
118146
# TODO(rtheis): Add port range support (type and code) for icmp
119147
# protocol. Until then, continue ignoring the port range.
120148
if parsed_args.proto != 'icmp':
@@ -126,8 +154,10 @@ def take_action_network(self, client, parsed_args):
126154
parsed_args.src_group,
127155
ignore_missing=False
128156
).id
129-
else:
157+
elif parsed_args.src_ip is not None:
130158
attrs['remote_ip_prefix'] = parsed_args.src_ip
159+
elif attrs['ethertype'] == 'IPv4':
160+
attrs['remote_ip_prefix'] = '0.0.0.0/0'
131161
attrs['security_group_id'] = security_group_id
132162

133163
# Create and show the security group rule.
@@ -145,17 +175,22 @@ def take_action_compute(self, client, parsed_args):
145175
from_port, to_port = -1, -1
146176
else:
147177
from_port, to_port = parsed_args.dst_port
178+
src_ip = None
148179
if parsed_args.src_group is not None:
149180
parsed_args.src_group = utils.find_resource(
150181
client.security_groups,
151182
parsed_args.src_group,
152183
).id
184+
if parsed_args.src_ip is not None:
185+
src_ip = parsed_args.src_ip
186+
else:
187+
src_ip = '0.0.0.0/0'
153188
obj = client.security_group_rules.create(
154189
group.id,
155190
parsed_args.proto,
156191
from_port,
157192
to_port,
158-
parsed_args.src_ip,
193+
src_ip,
159194
parsed_args.src_group,
160195
)
161196
return _format_security_group_rule_show(obj._info)

openstackclient/tests/network/v2/test_security_group_rule.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def test_create_no_options(self):
9797
self.assertRaises(tests_utils.ParserException,
9898
self.check_parser, self.cmd, [], [])
9999

100-
def test_create_source_group_and_ip(self):
100+
def test_create_all_source_options(self):
101101
arglist = [
102102
'--src-ip', '10.10.0.0/24',
103103
'--src-group', self._security_group.id,
@@ -114,6 +114,14 @@ def test_create_bad_protocol(self):
114114
self.assertRaises(tests_utils.ParserException,
115115
self.check_parser, self.cmd, arglist, [])
116116

117+
def test_create_bad_ethertype(self):
118+
arglist = [
119+
'--ethertype', 'foo',
120+
self._security_group.id,
121+
]
122+
self.assertRaises(tests_utils.ParserException,
123+
self.check_parser, self.cmd, arglist, [])
124+
117125
def test_create_default_rule(self):
118126
self._setup_security_group_rule({
119127
'port_range_max': 443,
@@ -124,6 +132,8 @@ def test_create_default_rule(self):
124132
self._security_group.id,
125133
]
126134
verifylist = [
135+
('dst_port', (self._security_group_rule.port_range_min,
136+
self._security_group_rule.port_range_max)),
127137
('group', self._security_group.id),
128138
]
129139
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -150,12 +160,14 @@ def test_create_source_group(self):
150160
})
151161
arglist = [
152162
'--dst-port', str(self._security_group_rule.port_range_min),
163+
'--ingress',
153164
'--src-group', self._security_group.name,
154165
self._security_group.id,
155166
]
156167
verifylist = [
157168
('dst_port', (self._security_group_rule.port_range_min,
158169
self._security_group_rule.port_range_max)),
170+
('ingress', True),
159171
('src_group', self._security_group.name),
160172
('group', self._security_group.id),
161173
]
@@ -206,6 +218,43 @@ def test_create_source_ip(self):
206218
self.assertEqual(tuple(self.expected_columns), columns)
207219
self.assertEqual(self.expected_data, data)
208220

221+
def test_create_network_options(self):
222+
self._setup_security_group_rule({
223+
'direction': 'egress',
224+
'ethertype': 'IPv6',
225+
'port_range_max': 443,
226+
'port_range_min': 443,
227+
'remote_group_id': None,
228+
'remote_ip_prefix': None,
229+
})
230+
arglist = [
231+
'--dst-port', str(self._security_group_rule.port_range_min),
232+
'--egress',
233+
'--ethertype', self._security_group_rule.ethertype,
234+
self._security_group.id,
235+
]
236+
verifylist = [
237+
('dst_port', (self._security_group_rule.port_range_min,
238+
self._security_group_rule.port_range_max)),
239+
('egress', True),
240+
('ethertype', self._security_group_rule.ethertype),
241+
('group', self._security_group.id),
242+
]
243+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
244+
245+
columns, data = self.cmd.take_action(parsed_args)
246+
247+
self.network.create_security_group_rule.assert_called_once_with(**{
248+
'direction': self._security_group_rule.direction,
249+
'ethertype': self._security_group_rule.ethertype,
250+
'port_range_max': self._security_group_rule.port_range_max,
251+
'port_range_min': self._security_group_rule.port_range_min,
252+
'protocol': self._security_group_rule.protocol,
253+
'security_group_id': self._security_group.id,
254+
})
255+
self.assertEqual(tuple(self.expected_columns), columns)
256+
self.assertEqual(self.expected_data, data)
257+
209258

210259
class TestCreateSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
211260

@@ -241,7 +290,7 @@ def test_create_no_options(self):
241290
self.assertRaises(tests_utils.ParserException,
242291
self.check_parser, self.cmd, [], [])
243292

244-
def test_create_source_group_and_ip(self):
293+
def test_create_all_source_options(self):
245294
arglist = [
246295
'--src-ip', '10.10.0.0/24',
247296
'--src-group', self._security_group.id,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
features:
3+
- Add ``--ingress``, ``--egress``, and ``--ethertype`` options to the
4+
``security group rule create`` command for Network v2 only. These
5+
options enable ``egress`` and ``IPv6`` security group rules.
6+
[Bug `1519512 <https://bugs.launchpad.net/bugs/1519512>`_]

0 commit comments

Comments
 (0)