Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/awscli/customizations/ec2/secgroupsimplify.py
1567 views
1
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License"). You
4
# may not use this file except in compliance with the License. A copy of
5
# the License is located at
6
#
7
# http://aws.amazon.com/apache2.0/
8
#
9
# or in the "license" file accompanying this file. This file is
10
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
# ANY KIND, either express or implied. See the License for the specific
12
# language governing permissions and limitations under the License.
13
"""
14
This customization adds the following scalar parameters to the
15
authorize operations:
16
17
* --protocol: tcp | udp | icmp or any protocol number
18
* --port: A single integer or a range (min-max). You can specify ``all``
19
to mean all ports (for example, port range 0-65535)
20
* --source-group: Either the source security group ID or name.
21
* --cidr - The IPv4 address range, in CIDR format. Cannot be used when specifying a source or
22
destination security group.
23
"""
24
25
from awscli.arguments import CustomArgument
26
27
28
def _add_params(argument_table, **kwargs):
29
arg = ProtocolArgument('protocol',
30
help_text=PROTOCOL_DOCS)
31
argument_table['protocol'] = arg
32
argument_table['ip-protocol']._UNDOCUMENTED = True
33
34
arg = PortArgument('port', help_text=PORT_DOCS)
35
argument_table['port'] = arg
36
# Port handles both the from-port and to-port,
37
# we need to not document both args.
38
argument_table['from-port']._UNDOCUMENTED = True
39
argument_table['to-port']._UNDOCUMENTED = True
40
41
arg = CidrArgument('cidr', help_text=CIDR_DOCS)
42
argument_table['cidr'] = arg
43
argument_table['cidr-ip']._UNDOCUMENTED = True
44
45
arg = SourceGroupArgument('source-group',
46
help_text=SOURCEGROUP_DOCS)
47
argument_table['source-group'] = arg
48
argument_table['source-security-group-name']._UNDOCUMENTED = True
49
50
arg = GroupOwnerArgument('group-owner',
51
help_text=GROUPOWNER_DOCS)
52
argument_table['group-owner'] = arg
53
argument_table['source-security-group-owner-id']._UNDOCUMENTED = True
54
55
56
def _check_args(parsed_args, **kwargs):
57
# This function checks the parsed args. If the user specified
58
# the --ip-permissions option with any of the scalar options we
59
# raise an error.
60
arg_dict = vars(parsed_args)
61
if arg_dict['ip_permissions']:
62
for key in ('protocol', 'port', 'cidr',
63
'source_group', 'group_owner'):
64
if arg_dict[key]:
65
msg = ('The --%s option is not compatible '
66
'with the --ip-permissions option ') % key
67
raise ValueError(msg)
68
69
70
def _add_docs(help_command, **kwargs):
71
doc = help_command.doc
72
doc.style.new_paragraph()
73
doc.style.start_note()
74
msg = ('To specify multiple rules in a single command '
75
'use the <code>--ip-permissions</code> option')
76
doc.include_doc_string(msg)
77
doc.style.end_note()
78
79
80
EVENTS = [
81
('building-argument-table.ec2.authorize-security-group-ingress',
82
_add_params),
83
('building-argument-table.ec2.authorize-security-group-egress',
84
_add_params),
85
('building-argument-table.ec2.revoke-security-group-ingress', _add_params),
86
('building-argument-table.ec2.revoke-security-group-egress', _add_params),
87
('operation-args-parsed.ec2.authorize-security-group-ingress',
88
_check_args),
89
('operation-args-parsed.ec2.authorize-security-group-egress', _check_args),
90
('operation-args-parsed.ec2.revoke-security-group-ingress', _check_args),
91
('operation-args-parsed.ec2.revoke-security-group-egress', _check_args),
92
('doc-description.ec2.authorize-security-group-ingress', _add_docs),
93
('doc-description.ec2.authorize-security-group-egress', _add_docs),
94
('doc-description.ec2.revoke-security-group-ingress', _add_docs),
95
('doc-description.ec2.revoke-security-groupdoc-ingress', _add_docs),
96
]
97
PROTOCOL_DOCS = ('<p>The IP protocol: <code>tcp</code> | '
98
'<code>udp</code> | <code>icmp</code></p> '
99
'<p>(VPC only) Use <code>all</code> to specify all protocols.</p>'
100
'<p>If this argument is provided without also providing the '
101
'<code>port</code> argument, then it will be applied to all '
102
'ports for the specified protocol.</p>')
103
PORT_DOCS = ('<p>For TCP or UDP: The range of ports to allow.'
104
' A single integer or a range (<code>min-max</code>).</p>'
105
'<p>For ICMP: A single integer or a range (<code>type-code</code>)'
106
' representing the ICMP type'
107
' number and the ICMP code number respectively.'
108
' A value of -1 indicates all ICMP codes for'
109
' all ICMP types. A value of -1 just for <code>type</code>'
110
' indicates all ICMP codes for the specified ICMP type.</p>')
111
CIDR_DOCS = '<p>The IPv4 address range, in CIDR format.</p>'
112
SOURCEGROUP_DOCS = ('<p>The name or ID of the source security group.</p>')
113
GROUPOWNER_DOCS = ('<p>The AWS account ID that owns the source security '
114
'group. Cannot be used when specifying a CIDR IP '
115
'address.</p>')
116
117
118
def register_secgroup(event_handler):
119
for event, handler in EVENTS:
120
event_handler.register(event, handler)
121
122
123
def _build_ip_permissions(params, key, value):
124
if 'IpPermissions' not in params:
125
params['IpPermissions'] = [{}]
126
if key == 'CidrIp':
127
if 'IpRanges' not in params['ip_permissions'][0]:
128
params['IpPermissions'][0]['IpRanges'] = []
129
params['IpPermissions'][0]['IpRanges'].append(value)
130
elif key in ('GroupId', 'GroupName', 'UserId'):
131
if 'UserIdGroupPairs' not in params['IpPermissions'][0]:
132
params['IpPermissions'][0]['UserIdGroupPairs'] = [{}]
133
params['IpPermissions'][0]['UserIdGroupPairs'][0][key] = value
134
else:
135
params['IpPermissions'][0][key] = value
136
137
138
class ProtocolArgument(CustomArgument):
139
140
def add_to_params(self, parameters, value):
141
if value:
142
try:
143
int_value = int(value)
144
if (int_value < 0 or int_value > 255) and int_value != -1:
145
msg = ('protocol numbers must be in the range 0-255 '
146
'or -1 to specify all protocols')
147
raise ValueError(msg)
148
except ValueError:
149
if value not in ('tcp', 'udp', 'icmp', 'all'):
150
msg = ('protocol parameter should be one of: '
151
'tcp|udp|icmp|all or any valid protocol number.')
152
raise ValueError(msg)
153
if value == 'all':
154
value = '-1'
155
_build_ip_permissions(parameters, 'IpProtocol', value)
156
157
158
class PortArgument(CustomArgument):
159
160
def add_to_params(self, parameters, value):
161
if value:
162
try:
163
if value == '-1' or value == 'all':
164
fromstr = '-1'
165
tostr = '-1'
166
elif '-' in value:
167
# We can get away with simple logic here because
168
# argparse will not allow values such as
169
# "-1-8", and these aren't actually valid
170
# values any from from/to ports.
171
fromstr, tostr = value.split('-', 1)
172
else:
173
fromstr, tostr = (value, value)
174
_build_ip_permissions(parameters, 'FromPort', int(fromstr))
175
_build_ip_permissions(parameters, 'ToPort', int(tostr))
176
except ValueError:
177
msg = ('port parameter should be of the '
178
'form <from[-to]> (e.g. 22 or 22-25)')
179
raise ValueError(msg)
180
181
182
class CidrArgument(CustomArgument):
183
184
def add_to_params(self, parameters, value):
185
if value:
186
value = [{'CidrIp': value}]
187
_build_ip_permissions(parameters, 'IpRanges', value)
188
189
190
class SourceGroupArgument(CustomArgument):
191
192
def add_to_params(self, parameters, value):
193
if value:
194
if value.startswith('sg-'):
195
_build_ip_permissions(parameters, 'GroupId', value)
196
else:
197
_build_ip_permissions(parameters, 'GroupName', value)
198
199
200
class GroupOwnerArgument(CustomArgument):
201
202
def add_to_params(self, parameters, value):
203
if value:
204
_build_ip_permissions(parameters, 'UserId', value)
205
206