# Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. require 'aws/ec2/resource' require 'aws/ec2/tagged_item' require 'aws/ec2/security_group/ip_permission' require 'aws/ec2/security_group/ip_permission_collection' module AWS class EC2 # Represents a security group in EC2. # # @attr_reader [String] description The short informal description # given when the group was created. # # @attr_reader [String] name The name of the security group. # # @attr_reader [String] owner_id The security group owner's id. # class SecurityGroup < Resource include TaggedItem def initialize id, options = {} @id = id @name = options[:name] @description = options[:description] @owner_id = options[:owner_id] super end # @return [String] The id of the security group. attr_reader :id alias_method :group_id, :id attribute :name, :as => :group_name, :static => true attribute :owner_id, :static => true attribute :description, :as => :group_description, :static => true attribute :ip_permissions_list, :as => :ip_permissions populates_from(:describe_security_groups) do |resp| resp.security_group_index[id] end # @return [Boolean] True if the security group exists. def exists? client.describe_security_groups(:filters => [ { :name => "group-id", :values => [id] } ]).security_group_index.key?(id) end # @return [SecurityGroup::IpPermissionCollection] Returns a # collection of {IpPermission} objects that represents all of # the permissions this security group has authorizations for. def ip_permissions IpPermissionCollection.new(self, :config => config) end # Adds ingress rules for ICMP pings. Defaults to 0.0.0.0/0 for # the list of allowed IP ranges the ping can come from. # # security_group.allow_ping # anyone can ping servers in this group # # # only allow ping from a particular address # security_group.allow_ping('123.123.123.123/0') # # @param [String] ip_ranges One or more IP ranges to allow ping from. # Defaults to 0.0.0.0/0 def allow_ping *sources sources << '0.0.0.0/0' if sources.empty? authorize_ingress('icmp', -1, *sources) end # Removes ingress rules for ICMP pings. Defaults to 0.0.0.0/0 for # the list of IP ranges to revoke. # # @param [String] ip_ranges One or more IP ranges to allow ping from. # Defaults to 0.0.0.0/0 def disallow_ping *sources sources << '0.0.0.0/0' if sources.empty? revoke_ingress('icmp', -1, *sources) end # Adds an ingress rules to a security group. # # Each ingress exception is comprised of a protocol a port range # and a list of sources. # # # This example grants the whole internet (0.0.0.0/0) access to port 80 # over TCP (HTTP web traffic). # # security_groups['websrv'].authorize_ingress(:tcp, 80) # # In the following example we grant SSH access from a list of # IP address. # # security_groups['appsrv'].authorize_ingress(:tcp, 22, # '111.111.111.111/0', '222.222.222.222/0') # # You can also grant privileges to other security groups. This # is a convenient shortcut for granting permissions to all EC2 # servers in a particular security group access. # # web = security_groups['httpservers'] # db = security_groups['dbservers'] # # db.authorize_ingress(:tcp, 3306, web) # # You can specify port ranges as well: # # security_groups['ftpsvr'].authorize_ingress(:tcp, 20..21) # # You can even mix and match IP address and security groups. # # @param [String, Symbol] protocol Should be :tcp, :udp or :icmp # or the string equivalent. # # @param [Integer, Range] ports The port (or port range) to allow # ingress traffic over. You can pass a single integer (like 80) # or a range (like 20..21). # # @param [Mixed] sources One or more CIDR IP addresses, # security groups, or hashes. Hash values should # have :group_id and :user_id keys/values. This is useful # for when the security group belongs to another account. The # user id should be the owner_id (account id) of the security # group. # # @return [nil] def authorize_ingress protocol, ports, *sources permissions = format_permission(protocol, ports, sources) client.authorize_security_group_ingress( :group_id => id, :ip_permissions => permissions) nil end # @param see #authorize_ingress # @return [nil] def revoke_ingress protocol, ports, *sources permissions = format_permission(protocol, ports, sources) client.revoke_security_group_ingress( :group_id => id, :ip_permissions => permissions) nil end # Deletes this security group. # # If you attempt to delete a security group that contains # instances, or attempt to delete a security group that is referenced # by another security group, an error is raised. For example, if # security group B has a rule that allows access from security # group A, security group A cannot be deleted until the rule is # removed. # @return [nil] def delete client.delete_security_group(:group_id => id) nil end # @private def resource_type 'security-group' end # @private def inflected_name "group" end # @private def self.describe_call_name :describe_security_groups end def describe_call_name; self.class.describe_call_name; end # @private protected def find_in_response(resp) resp.security_group_index[id] end # @private protected def format_permission protocol, ports, sources permission = {} permission[:ip_protocol] = protocol.to_s.downcase permission[:from_port] = Array(ports).first.to_i permission[:to_port] = Array(ports).last.to_i ip_ranges = [] groups = [] # default to 0.0.0.0/0 sources << '0.0.0.0/0' if sources.empty? sources.each do |where| case where when String ip_ranges << where when SecurityGroup groups << {:group_id => where.id, :user_id => where.owner_id} when Hash if where.has_key?(:group_id) and where.has_key?(:user_id) groups << where else raise ArgumentError, 'invalid ingress ip permission, hashes ' + 'must have :group_id and :user_id key/values' end else raise ArgumentError, 'invalid ingress ip permission, ' + 'expected CIDR IP addres or SecurityGroup' end end unless ip_ranges.empty? permission[:ip_ranges] = ip_ranges.collect{|ip| { :cidr_ip => ip } } end unless groups.empty? permission[:user_id_group_pairs] = groups end [permission] end end end end