Path: blob/develop/awscli/customizations/ec2/secgroupsimplify.py
1567 views
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.12"""13This customization adds the following scalar parameters to the14authorize operations:1516* --protocol: tcp | udp | icmp or any protocol number17* --port: A single integer or a range (min-max). You can specify ``all``18to mean all ports (for example, port range 0-65535)19* --source-group: Either the source security group ID or name.20* --cidr - The IPv4 address range, in CIDR format. Cannot be used when specifying a source or21destination security group.22"""2324from awscli.arguments import CustomArgument252627def _add_params(argument_table, **kwargs):28arg = ProtocolArgument('protocol',29help_text=PROTOCOL_DOCS)30argument_table['protocol'] = arg31argument_table['ip-protocol']._UNDOCUMENTED = True3233arg = PortArgument('port', help_text=PORT_DOCS)34argument_table['port'] = arg35# Port handles both the from-port and to-port,36# we need to not document both args.37argument_table['from-port']._UNDOCUMENTED = True38argument_table['to-port']._UNDOCUMENTED = True3940arg = CidrArgument('cidr', help_text=CIDR_DOCS)41argument_table['cidr'] = arg42argument_table['cidr-ip']._UNDOCUMENTED = True4344arg = SourceGroupArgument('source-group',45help_text=SOURCEGROUP_DOCS)46argument_table['source-group'] = arg47argument_table['source-security-group-name']._UNDOCUMENTED = True4849arg = GroupOwnerArgument('group-owner',50help_text=GROUPOWNER_DOCS)51argument_table['group-owner'] = arg52argument_table['source-security-group-owner-id']._UNDOCUMENTED = True535455def _check_args(parsed_args, **kwargs):56# This function checks the parsed args. If the user specified57# the --ip-permissions option with any of the scalar options we58# raise an error.59arg_dict = vars(parsed_args)60if arg_dict['ip_permissions']:61for key in ('protocol', 'port', 'cidr',62'source_group', 'group_owner'):63if arg_dict[key]:64msg = ('The --%s option is not compatible '65'with the --ip-permissions option ') % key66raise ValueError(msg)676869def _add_docs(help_command, **kwargs):70doc = help_command.doc71doc.style.new_paragraph()72doc.style.start_note()73msg = ('To specify multiple rules in a single command '74'use the <code>--ip-permissions</code> option')75doc.include_doc_string(msg)76doc.style.end_note()777879EVENTS = [80('building-argument-table.ec2.authorize-security-group-ingress',81_add_params),82('building-argument-table.ec2.authorize-security-group-egress',83_add_params),84('building-argument-table.ec2.revoke-security-group-ingress', _add_params),85('building-argument-table.ec2.revoke-security-group-egress', _add_params),86('operation-args-parsed.ec2.authorize-security-group-ingress',87_check_args),88('operation-args-parsed.ec2.authorize-security-group-egress', _check_args),89('operation-args-parsed.ec2.revoke-security-group-ingress', _check_args),90('operation-args-parsed.ec2.revoke-security-group-egress', _check_args),91('doc-description.ec2.authorize-security-group-ingress', _add_docs),92('doc-description.ec2.authorize-security-group-egress', _add_docs),93('doc-description.ec2.revoke-security-group-ingress', _add_docs),94('doc-description.ec2.revoke-security-groupdoc-ingress', _add_docs),95]96PROTOCOL_DOCS = ('<p>The IP protocol: <code>tcp</code> | '97'<code>udp</code> | <code>icmp</code></p> '98'<p>(VPC only) Use <code>all</code> to specify all protocols.</p>'99'<p>If this argument is provided without also providing the '100'<code>port</code> argument, then it will be applied to all '101'ports for the specified protocol.</p>')102PORT_DOCS = ('<p>For TCP or UDP: The range of ports to allow.'103' A single integer or a range (<code>min-max</code>).</p>'104'<p>For ICMP: A single integer or a range (<code>type-code</code>)'105' representing the ICMP type'106' number and the ICMP code number respectively.'107' A value of -1 indicates all ICMP codes for'108' all ICMP types. A value of -1 just for <code>type</code>'109' indicates all ICMP codes for the specified ICMP type.</p>')110CIDR_DOCS = '<p>The IPv4 address range, in CIDR format.</p>'111SOURCEGROUP_DOCS = ('<p>The name or ID of the source security group.</p>')112GROUPOWNER_DOCS = ('<p>The AWS account ID that owns the source security '113'group. Cannot be used when specifying a CIDR IP '114'address.</p>')115116117def register_secgroup(event_handler):118for event, handler in EVENTS:119event_handler.register(event, handler)120121122def _build_ip_permissions(params, key, value):123if 'IpPermissions' not in params:124params['IpPermissions'] = [{}]125if key == 'CidrIp':126if 'IpRanges' not in params['ip_permissions'][0]:127params['IpPermissions'][0]['IpRanges'] = []128params['IpPermissions'][0]['IpRanges'].append(value)129elif key in ('GroupId', 'GroupName', 'UserId'):130if 'UserIdGroupPairs' not in params['IpPermissions'][0]:131params['IpPermissions'][0]['UserIdGroupPairs'] = [{}]132params['IpPermissions'][0]['UserIdGroupPairs'][0][key] = value133else:134params['IpPermissions'][0][key] = value135136137class ProtocolArgument(CustomArgument):138139def add_to_params(self, parameters, value):140if value:141try:142int_value = int(value)143if (int_value < 0 or int_value > 255) and int_value != -1:144msg = ('protocol numbers must be in the range 0-255 '145'or -1 to specify all protocols')146raise ValueError(msg)147except ValueError:148if value not in ('tcp', 'udp', 'icmp', 'all'):149msg = ('protocol parameter should be one of: '150'tcp|udp|icmp|all or any valid protocol number.')151raise ValueError(msg)152if value == 'all':153value = '-1'154_build_ip_permissions(parameters, 'IpProtocol', value)155156157class PortArgument(CustomArgument):158159def add_to_params(self, parameters, value):160if value:161try:162if value == '-1' or value == 'all':163fromstr = '-1'164tostr = '-1'165elif '-' in value:166# We can get away with simple logic here because167# argparse will not allow values such as168# "-1-8", and these aren't actually valid169# values any from from/to ports.170fromstr, tostr = value.split('-', 1)171else:172fromstr, tostr = (value, value)173_build_ip_permissions(parameters, 'FromPort', int(fromstr))174_build_ip_permissions(parameters, 'ToPort', int(tostr))175except ValueError:176msg = ('port parameter should be of the '177'form <from[-to]> (e.g. 22 or 22-25)')178raise ValueError(msg)179180181class CidrArgument(CustomArgument):182183def add_to_params(self, parameters, value):184if value:185value = [{'CidrIp': value}]186_build_ip_permissions(parameters, 'IpRanges', value)187188189class SourceGroupArgument(CustomArgument):190191def add_to_params(self, parameters, value):192if value:193if value.startswith('sg-'):194_build_ip_permissions(parameters, 'GroupId', value)195else:196_build_ip_permissions(parameters, 'GroupName', value)197198199class GroupOwnerArgument(CustomArgument):200201def add_to_params(self, parameters, value):202if value:203_build_ip_permissions(parameters, 'UserId', value)204205206