Class: Asbestos::Host

Inherits:
Object
  • Object
show all
Includes:
ClassCollection
Defined in:
lib/asbestos/host.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ClassCollection

included

Constructor Details

#initialize(name) ⇒ Host

Returns a new instance of Host


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/asbestos/host.rb', line 28

def initialize(name)
  @name = name
  @groups = []
  @rulesets = []

  @chains = {}

  @interfaces = {} # maps interface's tag to /dev name
  @addresses = {} # maps interface's /dev name to an ip address


  Asbestos.with_indifferent_access! @chains
  Asbestos.with_indifferent_access! @interfaces
  Asbestos.with_indifferent_access! @addresses

  if generating_rules_for_current_host?
    Asbestos.interfaces.each do |if_name, info|
      @addresses[if_name] = info[:inet_addr]
    end
  end

  #
  # Define the necessary chains
  # # FIXME do we need :forward too?
  #
  [:input, :output].each do |name|
    chain(name, :accept)
  end

  self.class.all[name] = self
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(rule_set_name, args = {}) ⇒ Object

Missing methods should be the name of RuleSets, if not, raise an error

This is similar to the “runs” method above, but for RuleSets, rather than services.


238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/asbestos/host.rb', line 238

def method_missing(rule_set_name, args = {})
  template = Asbestos::RuleSet[rule_set_name]
  raise %{Unknown host DSL call : "#{rule_set_name}" for host "#{name}"} unless template

  @rulesets << \
    Asbestos::RuleSet.new(rule_set_name, self, template).tap do |rs|
      # override template defaults with provided options
      args.each do |k, v|
        rs.send k, v
      end
    end
end

Instance Attribute Details

#addressesObject (readonly)

Returns the value of attribute addresses


20
21
22
# File 'lib/asbestos/host.rb', line 20

def addresses
  @addresses
end

#chainsObject (readonly)

Returns the value of attribute chains


22
23
24
# File 'lib/asbestos/host.rb', line 22

def chains
  @chains
end

#groupsObject (readonly)

Returns the value of attribute groups


18
19
20
# File 'lib/asbestos/host.rb', line 18

def groups
  @groups
end

#interfacesObject (readonly)

Returns the value of attribute interfaces


19
20
21
# File 'lib/asbestos/host.rb', line 19

def interfaces
  @interfaces
end

#nameObject (readonly)

Returns the value of attribute name


17
18
19
# File 'lib/asbestos/host.rb', line 17

def name
  @name
end

#rulesetsObject (readonly)

Returns the value of attribute rulesets


21
22
23
# File 'lib/asbestos/host.rb', line 21

def rulesets
  @rulesets
end

#templateObject

the HostTemplate that built this host


25
26
27
# File 'lib/asbestos/host.rb', line 25

def template
  @template
end

Class Method Details

.[](name) ⇒ Object

returns a lazily evaluated block, to allow hosts to be defined in the DSL without a lot of hoopla


11
12
13
# File 'lib/asbestos/host.rb', line 11

def [](name)
  lambda { @all[name] }
end

Instance Method Details

#chain(name, default_action = :none) ⇒ Object

Defines a firewall chain on this host, this may be an IPTables-only concept.

The default_action here is also called the chain's “policy” in IPTables parlance


174
175
176
# File 'lib/asbestos/host.rb', line 174

def chain(name, default_action = :none)
  @chains[name.downcase.to_sym] = default_action
end

#debugObject


60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/asbestos/host.rb', line 60

def debug
  [
    "Hostname: #{@name}",
    (@template ? "  Template: #{@template}" : nil),
    "  Interfaces: #{@interfaces}",
    "  Addresses: #{@addresses}",
  ].tap do |a|
    a << "  Groups: #{@groups.sort.join(', ')}" unless @groups.empty?
    unless @rulesets.empty?
      a << "  RuleSets/Services:"
      @rulesets.each { |s| a << "    #{s.inspect}" }
    end
  end.join("\n")
end

#generating_rules_for_current_host?Boolean

Indicates if Asbestos is generating rules for the host it's running on

Returns:

  • (Boolean)

89
90
91
# File 'lib/asbestos/host.rb', line 89

def generating_rules_for_current_host?
  Asbestos.hostname.to_s == @name.to_s
end

#group(name = nil) ⇒ Object

Places this host in a named group

host 'dax' do

group :developers

end


100
101
102
103
104
105
106
107
108
# File 'lib/asbestos/host.rb', line 100

def group(name = nil)
  if name
    @groups << name
    self.class.groups[name] ||= []
    self.class.groups[name] << self
  else
    @groups
  end
end

#inspectObject Also known as: to_s


75
76
77
# File 'lib/asbestos/host.rb', line 75

def inspect
  "#<Host name:#{name}>"
end

#interface(tag, if_names, address = nil, &block) ⇒ Object

Defines an interface on this host with a given “tag”. The interface's address can be defined explicitly, or at runtime via a block.

host 'dax' do

group :developers

interface :external, :eth0  #=> address is "dax_external"
interface :dmz, [:eth1, :eth2]  #=> addresses are "dax_dmz_eth1" and "dax_dmz_eth2"

interface :internal, :eth3 do |host|
  [host.group, host.name, 'foo'].join('_')
end  #=> address is "developers_dax_foo"

interface :internal, :eth4, 'bar' #=> address is "bar"

end


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
# File 'lib/asbestos/host.rb', line 127

def interface(tag, if_names, address = nil, &block)
  interfaces = [*@interfaces[tag], *if_names].compact.uniq
  raise "single address, #{address}, given for multiple interfaces, #{interfaces}, on host #{name}" if interfaces.length > 1 && address

  @interfaces[tag] = interfaces

  # determine the address for each interface
  interfaces.each do |if_name|
    new_address = \
      if !address
        if block_given? 
          yield(self, if_name)
        else
          if interfaces.length > 1
            "#{name}_#{tag}_#{if_name}"
          else
            "#{name}_#{tag}"
          end
        end
      else
        address
      end
    @addresses[if_name] = new_address
  end

end

#log_denialsObject

Indicates that this host should log denied firewall packets.

host 'dax' do

log_denials

end


160
161
162
# File 'lib/asbestos/host.rb', line 160

def log_denials
  @log_denials = true
end

#log_denials?Boolean

Returns:

  • (Boolean)

164
165
166
# File 'lib/asbestos/host.rb', line 164

def log_denials?
  !!@log_denials
end

#rulesObject

Determine this host's firewall rules, according to the firewall type.


208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/asbestos/host.rb', line 208

def rules
  #
  # This is called first in case any preable needs to be declared (chains, specifically)
  #
  _ruleset_rules = ruleset_rules

  [
    Asbestos.firewall.preamble(self),
    _ruleset_rules,
    Asbestos.firewall.postamble(self)
  ].flatten
end

#ruleset_rulesObject

Ask each ruleset/service to generate its rules.


224
225
226
227
228
229
230
231
# File 'lib/asbestos/host.rb', line 224

def ruleset_rules
  @rulesets.collect do |r|
    ["# Begin [#{r.name}]",
     r.firewall_rules,
     "# End [#{r.name}]",
     ""]
  end
end

#runs(service_name, args = {}) ⇒ Object

Indicates that this host should have rules to allow the corresponding service to run on it. The arguments provided after the service name should be valid DSL calls supported by the service. Certain DSL calls come standard with all services, see the Service class for more info.

host 'dax' do

runs :nginx, :on => :external
runs :ssh,   :on => :internal, :port => 22022
runs :riak,  :on => :internal, :from => {:riak_cluster => :internal}

end


190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/asbestos/host.rb', line 190

def runs(service_name, args = {})
  template = Asbestos::Service[service_name]
  raise "Service not defined: #{service_name}" unless template

  @rulesets <<
    Asbestos::Service.new(service_name, self).tap do |s|
      s.instance_eval &template
      # override template defaults with provided options
      args.each do |k, v|
        s.send k, v
      end
    end
end