Class/Module Index [+]

Quicksearch

Ironfan::Provider::Ec2::SecurityGroup

Constants

WIDE_OPEN

Public Class Methods

ensure_groups(computer) click to toggle source

Utility

# File lib/ironfan/provider/ec2/security_group.rb, line 183
def self.ensure_groups(computer)
  return unless Ec2.applicable computer
  # Ensure the security_groups include those for cluster & facet
  # FIXME: This violates the DSL's immutability; it should be
  #   something calculated from within the DSL construction
  Ironfan.todo("CODE SMELL: violation of DSL immutability: #{caller}")
  cloud = computer.server.cloud(:ec2)
  c_group = cloud.security_group(computer.server.cluster_name)
  c_group.authorized_by_group(c_group.name)
  facet_name = "#{computer.server.cluster_name}-#{computer.server.facet_name}"
  cloud.security_group(facet_name)
end
expected_ids(computer) click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 21
def self.expected_ids(computer)
  ec2 = computer.server.cloud(:ec2)
  ec2.security_groups.keys.map { |name| group_name_with_vpc(name,ec2.vpc) }.uniq
end
group_name_with_vpc(name,vpc_id=nil) click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 172
def self.group_name_with_vpc(name,vpc_id=nil)
  vpc_id.nil? ? name.to_s : "#{vpc_id}:#{name.to_s}"
end
load!(cluster=nil) click to toggle source

Discovery

# File lib/ironfan/provider/ec2/security_group.rb, line 33
def self.load!(cluster=nil)
  Ec2.connection.security_groups.reject { |raw| raw.blank? }.each do |raw|
    sg = SecurityGroup.new(:adaptee => raw)
    remember(sg)
    Chef::Log.debug("Loaded #{sg}: #{sg.inspect}")
  end
end
most_appropriate_group_name(group, vpc_id, all_valid_groups) click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 176
def self.most_appropriate_group_name(group, vpc_id, all_valid_groups)
  all_valid_groups.include?(group_name_with_vpc(group, vpc_id)) ? group_name_with_vpc(group, vpc_id) : group
end
multiple?() click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 19
def self.multiple?()    true;   end
prepare!(computers) click to toggle source

Manipulation

# File lib/ironfan/provider/ec2/security_group.rb, line 65
def self.prepare!(computers)

  # Create any groups that don't yet exist, and ensure any authorizations
  # that are required for those groups
  cluster_name             = nil
  groups_to_create         = [ ]
  authorizations_to_ensure = [ ]

  # First, deduce the list of all groups to which at least one instance belongs
  # We'll use this later to decide whether to create groups, or authorize access,
  # using a VPC security group or an EC2 security group.
  groups_that_should_exist = computers.map { |c| expected_ids(c) }.flatten.sort.uniq
  groups_to_create << groups_that_should_exist

  computers.select { |computer| Ec2.applicable computer }.each do |computer|
    ensure_groups(computer) # Add facet and cluster security groups for the computer
    cloud           = computer.server.cloud(:ec2)
    cluster_name    = computer.server.cluster_name

    # Iterate over all of the security group information, keeping track of
    # any groups that must exist and any authorizations that must be ensured
    cloud.security_groups.values.each do |dsl_group|

      groups_to_create << dsl_group.name

      groups_to_create << dsl_group.group_authorized.map do |other_group|
        most_appropriate_group_name(other_group, cloud.vpc, groups_that_should_exist)
      end

      groups_to_create << dsl_group.group_authorized_by.map do |other_group|
        most_appropriate_group_name(other_group, cloud.vpc, groups_that_should_exist)
      end

      authorizations_to_ensure << dsl_group.group_authorized.map do |other_group|
        {
          :grantor      => most_appropriate_group_name(dsl_group.name, cloud.vpc, groups_that_should_exist),
          :grantee      => most_appropriate_group_name(other_group, cloud.vpc, groups_that_should_exist),
          :grantee_type => :group,
          :range        => WIDE_OPEN,
        }
      end

      authorizations_to_ensure << dsl_group.group_authorized_by.map do |other_group|
        {
          :grantor      => most_appropriate_group_name(other_group, cloud.vpc, groups_that_should_exist),
          :grantee      => most_appropriate_group_name(dsl_group.name, cloud.vpc, groups_that_should_exist),
          :grantee_type => :group,
          :range        => WIDE_OPEN,
        }
      end

      authorizations_to_ensure << dsl_group.range_authorizations.map do |range_auth|
        range, cidr, protocol = range_auth
        {
          :grantor      => group_name_with_vpc(dsl_group.name, cloud.vpc),
          :grantee      => { :cidr_ip => cidr, :ip_protocol => protocol },
          :grantee_type => :cidr,
          :range        => range,
        }
      end
    end
  end
  groups_to_create         = groups_to_create.flatten.uniq.reject { |group| recall? group.to_s }.sort
  authorizations_to_ensure = authorizations_to_ensure.flatten.uniq.sort { |a,b| a[:grantor] <=> b[:grantor] }

  Ironfan.step(cluster_name, "creating security groups", :blue) unless groups_to_create.empty?
  groups_to_create.each do |group|
    if group =~ /\//
      Ironfan.step(group, "  assuming that owner/group pair #{group} already exists", :blue)
    else
      Ironfan.step(group, "  creating #{group} security group", :blue)
      begin
        tokens    = group.to_s.split(':')
        group_id  = tokens.pop
        vpc_id    = tokens.pop
        Ec2.connection.create_security_group(group_id,"Ironfan created group #{group_id}",vpc_id)
      rescue Fog::Compute::AWS::Error => e # InvalidPermission.Duplicate
        Chef::Log.info("ignoring security group error: #{e}")
      end
    end
  end

  # Re-load everything so that we have a @@known list of security groups to manipulate
  load! unless groups_to_create.empty?

  # Now make sure that all required authorizations are present
  Ironfan.step(cluster_name, "ensuring security group permissions", :blue) unless authorizations_to_ensure.empty?
  authorizations_to_ensure.each do |auth|
    grantor_fog = recall(auth[:grantor])
    if :group == auth[:grantee_type]
      if fog_grantee = recall(auth[:grantee])
        options = { :group => fog_grantee.group_id }
      elsif auth[:grantee] =~ /\//
        options = { :group_alias => auth[:grantee] }
      else
        raise "Don't know what to do with authorization grantee #{auth[:grantee]}"
      end
      message = "  ensuring access from #{auth[:grantee]} to #{auth[:grantor]}"
    else
      options = auth[:grantee]
      message = "  ensuring #{auth[:grantee][:ip_protocol]} access from #{auth[:grantee][:cidr_ip]} to #{auth[:range]}"
    end
    Ironfan.step(auth[:grantor], message, :blue)
    safely_authorize(grantor_fog, auth[:range], options)
  end
end
resource_type() click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 20
def self.resource_type()        :security_group;   end
safely_authorize(fog_group,range,options) click to toggle source

Try an authorization, ignoring duplicates (this is easier than correlating). Do so for both TCP and UDP, unless only one is specified

# File lib/ironfan/provider/ec2/security_group.rb, line 198
def self.safely_authorize(fog_group,range,options)
  if options[:group_alias]
    owner, group = options[:group_alias].split(/\//)
    self.patiently(fog_group.name, Fog::Compute::AWS::Error, :ignore => Proc.new { |e| e.message =~ /InvalidPermission\.Duplicate/ }) do
      Ec2.connection.authorize_security_group_ingress(
        'GroupName'                   => fog_group.name,
        'SourceSecurityGroupName'     => group,
        'SourceSecurityGroupOwnerId'  => owner
      )
    end
  elsif options[:ip_protocol]
    self.patiently(fog_group.name, Fog::Compute::AWS::Error, :ignore => Proc.new { |e| e.message =~ /InvalidPermission\.Duplicate/ }) do
      fog_group.authorize_port_range(range,options)
    end
  else
    safely_authorize(fog_group,range,options.merge(:ip_protocol => 'tcp'))
    safely_authorize(fog_group,range,options.merge(:ip_protocol => 'udp'))
    safely_authorize(fog_group,Range.new(-1,-1),options.merge(:ip_protocol => 'icmp')) if(range == WIDE_OPEN)
    return
  end
end
shared?() click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 18
def self.shared?()      true;   end

Public Instance Methods

name() click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 26
def name()
  self.class.group_name_with_vpc(adaptee.name, adaptee.vpc_id)
end
receive_adaptee(obj) click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 41
def receive_adaptee(obj)
  obj = Ec2.connection.security_groups.new(obj) if obj.is_a?(Hash)
  super
end
to_s() click to toggle source
# File lib/ironfan/provider/ec2/security_group.rb, line 46
def to_s
  if ip_permissions.present?
    perm_str = ip_permissions.map{|perm|
      "%s:%s-%s (%s | %s)" % [
        perm['ipProtocol'], perm['fromPort'], perm['toPort'],
        perm['groups'  ].map{|el| el['groupName'] }.join(','),
        perm['ipRanges'].map{|el| el['cidrIp']    }.join(','),
      ]
    }
    return "<%-15s %-12s %-25s %s>" % [ self.class.handle, group_id, name, perm_str]
  else
    return "<%-15s %-12s %s>" % [ self.class.handle, group_id, name ]
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.