Class: Ironfan::Provider::Ec2::SecurityGroup
- Defined in:
- lib/ironfan/headers.rb,
lib/ironfan/provider/ec2/security_group.rb
Constant Summary collapse
- WIDE_OPEN =
(-1..-1)
Instance Attribute Summary
Attributes inherited from Resource
Class Method Summary collapse
-
.ensure_groups(computer) ⇒ Object
Utility.
- .expected_ids(computer) ⇒ Object
- .group_name_with_vpc(name, vpc_id = nil) ⇒ Object
-
.load!(cluster = nil) ⇒ Object
Discovery.
- .most_appropriate_group_name(group, vpc_id) ⇒ Object
- .multiple? ⇒ Boolean
-
.prepare!(computers) ⇒ Object
Manipulation.
- .resource_type ⇒ Object
-
.safely_authorize(fog_group, range, options) ⇒ Object
Try an authorization, ignoring duplicates (this is easier than correlating).
- .shared? ⇒ Boolean
Instance Method Summary collapse
Methods inherited from Resource
aggregate!, #bogus?, create!, destroy!, forget, forget!, handle, known, #on_correlate, patiently, recall, recall?, receive, register, remember, save!, validate_computer!, validate_resources!
Methods inherited from Builder
Class Method Details
.ensure_groups(computer) ⇒ Object
Utility
201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 201 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}") server = computer.server cluster_name = "#{computer.server.realm_name}-#{computer.server.cluster_name}" server.security_group computer.server.realm_name realm_group = server.security_group cluster_name realm_group. realm_group.name end |
.expected_ids(computer) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 21 def self.expected_ids(computer) return unless computer.server ec2 = computer.server.cloud(:ec2) server_groups = computer.server.security_groups cloud_groups = ec2.security_groups result = [] [server_groups, cloud_groups].each do |container| container.keys.each { |name| result.push( group_name_with_vpc(name,ec2.vpc) )} end return result.uniq end |
.group_name_with_vpc(name, vpc_id = nil) ⇒ Object
190 191 192 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 190 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) ⇒ Object
Discovery
43 44 45 46 47 48 49 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 43 def self.load!(cluster=nil) Ec2.connection.security_groups.reject { |raw| raw.blank? }.each do |raw| sg = SecurityGroup.new(:adaptee => raw) remember sg remember(sg, :id => sg.name.gsub( /^vpc-[^:]+:/, '') ) end end |
.most_appropriate_group_name(group, vpc_id) ⇒ Object
194 195 196 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 194 def self.most_appropriate_group_name(group, vpc_id) vpc_id.present? ? group_name_with_vpc(group, vpc_id) : group end |
.multiple? ⇒ Boolean
19 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 19 def self.multiple?() true; end |
.prepare!(computers) ⇒ Object
Manipulation
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 75 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 = [ ] = [ ] computers.each{|comp| ensure_groups(comp) if Ec2.applicable(comp) } # Add facet and cluster security groups for the computer # 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{|comp| expected_ids(comp) }.flatten.compact.sort.uniq groups_to_create << groups_that_should_exist computers.select { |computer| Ec2.applicable computer }.each do |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 [computer.server.security_groups, cloud.security_groups].each do |container| container.values.each do |dsl_group| groups_to_create << dsl_group.name groups_to_create << dsl_group..map do |other_group| most_appropriate_group_name(other_group, cloud.vpc) end groups_to_create << dsl_group..map do |other_group| most_appropriate_group_name(other_group, cloud.vpc) end << dsl_group..map do |other_group| { :grantor => most_appropriate_group_name(dsl_group.name, cloud.vpc), :grantee => most_appropriate_group_name(other_group, cloud.vpc), :grantee_type => :group, :range => WIDE_OPEN, } end << dsl_group..map do |other_group| { :grantor => most_appropriate_group_name(other_group, cloud.vpc), :grantee => most_appropriate_group_name(dsl_group.name, cloud.vpc), :grantee_type => :group, :range => WIDE_OPEN, } end << dsl_group..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 end groups_to_create = groups_to_create.flatten.uniq.reject { |group| recall? group.to_s }.sort = .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 case e. when /SecurityGroupLimitExceeded/ raise e else Chef::Log.info("ignoring security group error: #{e}") end 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 .empty? .each do |auth| grantor_fog = recall(auth[:grantor]) if :group == auth[:grantee_type] if fog_grantee = recall(auth[:grantee]) = { :group => fog_grantee.group_id } elsif auth[:grantee] =~ /\// = { :group_alias => auth[:grantee] } else raise "Don't know what to do with authorization grantee #{auth[:grantee]}" end = " ensuring access from #{auth[:grantee]} to #{auth[:grantor]}" else = auth[:grantee] = " ensuring #{auth[:grantee][:ip_protocol]} access from #{auth[:grantee][:cidr_ip]} to #{auth[:range]}" end Ironfan.step(auth[:grantor], , :blue) (grantor_fog, auth[:range], ) end end |
.resource_type ⇒ Object
20 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 20 def self.resource_type() :security_group; end |
.safely_authorize(fog_group, range, options) ⇒ Object
Try an authorization, ignoring duplicates (this is easier than correlating). Do so for both TCP and UDP, unless only one is specified
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 216 def self.(fog_group,range,) if [:group_alias] # In this case, we must first extract the group name # before recursively calling this function with it. owner, group = .delete(:group_alias).split(/\//) Chef::Log.debug("authorizing group alias #{[:group_alias].inspect} to group #{fog_group.name}") group_id = Ec2.connection.security_groups.get(group).group_id (fog_group, range, .merge(group: group_id)) elsif [:ip_protocol] # In this case, we've received the ip_protocol. With or # without a group name, we have enough information to open # the security group. Chef::Log.debug("authorizing to #{fog_group.name} with options #{.inspect}") self.patiently(fog_group.name, Fog::Compute::AWS::Error, :ignore => Proc.new { |e| e. =~ /Duplicate/ }) do fog_group.(range,) end else # Without an IP protocol, we'll open all of the relevant # ones. On non-VPC, that means tcp, udp, and icmp. On VPC, # that means -1 for all protocols. Chef::Log.debug([ "didn't receive ip_protocol for authorization to #{fog_group.name} ", "with options #{.inspect}. assuming all protocols" ].join) if fog_group.vpc_id.nil? # Non-VPC does not support -1 for all protocols, so # we'll need to do each protocol indendently. If we # haven't received an ip_protocol, we'll assume the user # meant to open everything. (fog_group, 1..65535, .merge(:ip_protocol => 'tcp')) (fog_group, 1..65535, .merge(:ip_protocol => 'udp')) (fog_group, -1..-1, .merge(:ip_protocol => 'icmp')) else # In VPC, we should use only one rule to conserve rules. (fog_group,range,.merge(:ip_protocol => -1)) end end end |
.shared? ⇒ Boolean
18 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 18 def self.shared?() true; end |
Instance Method Details
#name ⇒ Object
36 37 38 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 36 def name() self.class.group_name_with_vpc(adaptee.name, adaptee.vpc_id) end |
#receive_adaptee(obj) ⇒ Object
51 52 53 54 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 51 def receive_adaptee(obj) obj = Ec2.connection.security_groups.new(obj) if obj.is_a?(Hash) super end |
#to_s ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/ironfan/provider/ec2/security_group.rb', line 56 def to_s if .present? perm_str = .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 |