Class: Inspec::Resources::UnixHostProvider

Inherits:
HostProvider show all
Defined in:
lib/inspec/resources/host.rb

Direct Known Subclasses

DarwinHostProvider, LinuxHostProvider

Instance Attribute Summary

Attributes inherited from HostProvider

#inspec

Instance Method Summary collapse

Constructor Details

#initialize(inspec) ⇒ UnixHostProvider

Returns a new instance of UnixHostProvider.



167
168
169
170
171
172
173
# File 'lib/inspec/resources/host.rb', line 167

def initialize(inspec)
  super

  @has_nc = inspec.command("nc").exist?
  @has_ncat = inspec.command("ncat").exist?
  @has_net_redirections = inspec.command("strings `which bash` | grep -qE '/dev/(tcp|udp)/'").exit_status == 0
end

Instance Method Details

#missing_requirements(protocol) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/inspec/resources/host.rb', line 175

def missing_requirements(protocol)
  missing = []

  if %w{tcp udp}.include?(protocol) && !@has_nc && !@has_ncat
    if @has_net_redirections
      missing << "#{timeout} (part of coreutils) or netcat must be installed" unless inspec.command(timeout).exist?
    else
      missing << "netcat must be installed"
    end
  end

  missing
end

#netcat_check_command(hostname, port, protocol) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/inspec/resources/host.rb', line 208

def netcat_check_command(hostname, port, protocol)
  if @has_nc
    base_cmd = "nc"
  elsif @has_ncat
    base_cmd = "ncat"
  else
    return
  end

  if protocol == "udp"
    extra_flags = "-u"
  else
    extra_flags = ""
  end

  "echo | #{base_cmd} -v -w 1 #{extra_flags} #{hostname} #{port}"
end

#ping(hostname, port, protocol) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/inspec/resources/host.rb', line 189

def ping(hostname, port, protocol)
  if %w{tcp udp}.include?(protocol)
    if @has_nc || @has_ncat
      resp = inspec.command(netcat_check_command(hostname, port, protocol))
    else
      resp = inspec.command("#{timeout} 1 bash -c \"< /dev/#{protocol}/#{hostname}/#{port}\"")
    end
  else
    # fall back to ping, but we can only test ICMP packages with ping
    resp = inspec.command("ping -w 1 -c 1 #{hostname}")
  end

  {
    success: resp.exit_status.to_i == 0,
    connection: resp.stderr,
    socket: resp.stdout,
  }
end

#resolve_with_dig(hostname) ⇒ Object



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/inspec/resources/host.rb', line 230

def resolve_with_dig(hostname)
  addresses = []

  # look for IPv4 addresses
  cmd = inspec.command("dig +short A #{hostname}")
  cmd.stdout.lines.each do |line|
    matched = line.chomp.match(Resolv::IPv4::Regex)
    addresses << matched.to_s unless matched.nil?
  end

  # look for IPv6 addresses
  cmd = inspec.command("dig +short AAAA #{hostname}")
  cmd.stdout.lines.each do |line|
    matched = line.chomp.match(Resolv::IPv6::Regex)
    addresses << matched.to_s unless matched.nil?
  end

  addresses.empty? ? nil : addresses
end

#resolve_with_getent(hostname) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/inspec/resources/host.rb', line 250

def resolve_with_getent(hostname)
  cmd = inspec.command("getent ahosts #{hostname}")
  return nil unless cmd.exit_status.to_i == 0

  # getent ahosts output is formatted like so:
  # $ getent ahosts www.google.com
  # 172.217.8.4     STREAM www.google.com
  # 172.217.8.4     DGRAM
  # 172.217.8.4     RAW
  # 2607:f8b0:4004:803::2004 STREAM
  # 2607:f8b0:4004:803::2004 DGRAM
  # 2607:f8b0:4004:803::2004 RAW
  addresses = []
  cmd.stdout.lines.each do |line|
    ip, = line.split(/\s+/, 2)
    next unless ip.match(Resolv::IPv4::Regex) || ip.match(Resolv::IPv6::Regex)

    addresses << ip unless addresses.include?(ip)
  end

  addresses
end

#timeoutObject



226
227
228
# File 'lib/inspec/resources/host.rb', line 226

def timeout
  "timeout"
end