inspec/test/unit/resources/host_test.rb
Bryan McLellan dada8ea074 Add the generic 'darwin' to the service resource
macOS 11 Big Sur will be released later this year. Current beta versions
return 10.16 as the version, but the product name has changed from 'Mac
OS X' to 'macOS'. Train probably needs to be modified to deprecate
'mac_os_x' as a platform in favor of 'macos' but that would be a
significant downstream change. Train does fall back to 'darwin' on macOS
10.16, so by adding darwin to the list of platform names for the service
resource we are able to work around this for the moment.

This is the only location where mac_os_x is currently being used in
InSpec. Because we're in a case statement on platform rather than the
more generic platform family, we can't simply remove mac_os_x in favor
of darwin.

Signed-off-by: Bryan McLellan <btm@loftninjas.org>
2020-07-02 09:36:27 -04:00

359 lines
14 KiB
Ruby

require "helper"
require "inspec/resource"
require "inspec/resources/host"
describe "Inspec::Resources::Host" do
it "check host ping on ubuntu with dig" do
resource = MockLoader.new(:ubuntu1404).load_resource("host", "example.com")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com"
end
it "check host ping on centos 7" do
resource = MockLoader.new(:centos7).load_resource("host", "example.com")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com"
end
it "check host ping on darwin" do
resource = MockLoader.new(:macos10_10).load_resource("host", "example.com")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com"
end
it "check host ping on windows" do
resource = MockLoader.new(:windows).load_resource("host", "microsoft.com")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal false
_(resource.ipaddress).must_equal ["134.170.185.46", "134.170.188.221"]
_(resource.to_s).must_equal "Host microsoft.com"
end
it "check host ping on unsupported os" do
resource = MockLoader.new(:undefined).load_resource("host", "example.com")
_(resource.resolvable?).must_equal false
_(resource.reachable?).must_equal false
_(resource.ipaddress).must_be_nil
_(resource.to_s).must_equal "Host example.com"
end
it "check host tcp on ubuntu" do
resource = MockLoader.new(:ubuntu1404).load_resource("host", "example.com", port: 1234, protocol: "tcp")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com port 1234 proto tcp"
end
it "check host udp on ubuntu" do
resource = MockLoader.new(:ubuntu1404).load_resource("host", "example.com", port: 1234, protocol: "udp")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com port 1234 proto udp"
end
it "check host tcp on centos 7" do
resource = MockLoader.new(:centos7).load_resource("host", "example.com", port: 1234, protocol: "tcp")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com port 1234 proto tcp"
end
it "check host udp on centos 7" do
resource = MockLoader.new(:centos7).load_resource("host", "example.com", port: 1234, protocol: "udp")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com port 1234 proto udp"
end
it "check host tcp on darwin" do
resource = MockLoader.new(:macos10_10).load_resource("host", "example.com", port: 1234, protocol: "tcp")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com port 1234 proto tcp"
end
it "check host udp on darwin" do
resource = MockLoader.new(:macos10_10).load_resource("host", "example.com", port: 1234, protocol: "udp")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["12.34.56.78", "2606:2800:220:1:248:1893:25c8:1946"]
_(resource.to_s).must_equal "Host example.com port 1234 proto udp"
end
it "check host tcp on windows" do
resource = MockLoader.new(:windows).load_resource("host", "microsoft.com", port: 1234, protocol: "tcp")
_(resource.resolvable?).must_equal true
_(resource.reachable?).must_equal true
_(resource.ipaddress).must_equal ["134.170.185.46", "134.170.188.221"]
_(resource.to_s).must_equal "Host microsoft.com port 1234 proto tcp"
end
it "check host tcp on unsupported os" do
resource = MockLoader.new(:undefined).load_resource("host", "example.com", port: 1234, protocol: "tcp")
_(resource.resolvable?).must_equal false
_(resource.reachable?).must_equal false
_(resource.ipaddress).must_be_nil
_(resource.to_s).must_equal "Host example.com port 1234 proto tcp"
end
end
describe Inspec::Resources::UnixHostProvider do
let(:provider) { Inspec::Resources::UnixHostProvider.new(inspec) }
let(:inspec) { mock("inspec-backend") }
let(:nc_command) { mock("nc-command") }
let(:ncat_command) { mock("ncat-command") }
let(:timeout_command) { mock("timeout-command") }
let(:strings_command) { mock("strings-command") }
before do
inspec.stubs(:command).with("nc").returns(nc_command)
inspec.stubs(:command).with("ncat").returns(ncat_command)
inspec.stubs(:command).with("timeout").returns(timeout_command)
inspec.stubs(:command).with("gtimeout").returns(timeout_command)
inspec.stubs(:command).with("strings `which bash` | grep -qE '/dev/(tcp|udp)/'").returns(strings_command)
end
describe "#resolve_with_dig" do
let(:v4_command) { mock("v4_command") }
let(:v6_command) { mock("v6_command") }
before do
strings_command.stubs(:exit_status).returns(0)
nc_command.stubs(:exist?).returns(false)
ncat_command.stubs(:exist?).returns(false)
end
it "returns an array of IP addresses" do
ipv4_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
12.34.56.78
EOL
ipv6_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
2A03:2880:F112:83:FACE:B00C::25DE
EOL
v4_command.stubs(:stdout).returns(ipv4_command_output)
v6_command.stubs(:stdout).returns(ipv6_command_output)
inspec.stubs(:command).with("dig +short AAAA testdomain.com").returns(v6_command)
inspec.stubs(:command).with("dig +short A testdomain.com").returns(v4_command)
_(provider.resolve_with_dig("testdomain.com")).must_equal(["12.34.56.78", "2A03:2880:F112:83:FACE:B00C::25DE"])
end
it "returns only v4 addresses if no v6 addresses are available" do
ipv4_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
12.34.56.78
EOL
ipv6_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
EOL
v4_command.stubs(:stdout).returns(ipv4_command_output)
v6_command.stubs(:stdout).returns(ipv6_command_output)
inspec.stubs(:command).with("dig +short AAAA testdomain.com").returns(v6_command)
inspec.stubs(:command).with("dig +short A testdomain.com").returns(v4_command)
_(provider.resolve_with_dig("testdomain.com")).must_equal(["12.34.56.78"])
end
it "returns only v6 addresses if no v4 addresses are available" do
ipv4_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
EOL
ipv6_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
2A03:2880:F112:83:FACE:B00C::25DE
EOL
v4_command.stubs(:stdout).returns(ipv4_command_output)
v6_command.stubs(:stdout).returns(ipv6_command_output)
inspec.stubs(:command).with("dig +short AAAA testdomain.com").returns(v6_command)
inspec.stubs(:command).with("dig +short A testdomain.com").returns(v4_command)
_(provider.resolve_with_dig("testdomain.com")).must_equal(["2A03:2880:F112:83:FACE:B00C::25DE"])
end
it "returns nil if no addresses are available" do
ipv4_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
EOL
ipv6_command_output = <<~EOL
a.cname.goes.here
another.cname.cool
EOL
v4_command.stubs(:stdout).returns(ipv4_command_output)
v6_command.stubs(:stdout).returns(ipv6_command_output)
inspec.stubs(:command).with("dig +short AAAA testdomain.com").returns(v6_command)
inspec.stubs(:command).with("dig +short A testdomain.com").returns(v4_command)
_(provider.resolve_with_dig("testdomain.com")).must_be_nil
end
end
describe "#resolve_with_getent" do
before do
strings_command.stubs(:exit_status).returns(0)
nc_command.stubs(:exist?).returns(false)
ncat_command.stubs(:exist?).returns(false)
end
it "returns an array of IP addresses when successful" do
command_output = "123.123.123.123 STREAM testdomain.com\n2607:f8b0:4004:805::200e STREAM\n"
command = mock("getent_command")
command.stubs(:stdout).returns(command_output)
command.stubs(:exit_status).returns(0)
inspec.stubs(:command).with("getent ahosts testdomain.com").returns(command)
_(provider.resolve_with_getent("testdomain.com")).must_equal(["123.123.123.123", "2607:f8b0:4004:805::200e"])
end
it "returns nil if command is not successful" do
command = mock("getent_command")
command.stubs(:exit_status).returns(1)
inspec.stubs(:command).with("getent ahosts testdomain.com").returns(command)
_(provider.resolve_with_getent("testdomain.com")).must_be_nil
end
end
describe "#ping" do
let(:command_response) { mock("response") }
before do
strings_command.stubs(:exit_status).returns(0)
ncat_command.stubs(:exist?).returns(false)
command_response.stubs(:exit_status).returns("0")
command_response.stubs(:stdout).returns("foo")
command_response.stubs(:stderr).returns("bar")
end
it "calls netcat if available" do
nc_command.stubs(:exist?).returns(true)
inspec.expects(:command).with("echo | nc -v -w 1 example.com 1234").returns(command_response)
provider.ping("example.com", "1234", "tcp")
end
it "uses bash if netcat not available" do
nc_command.stubs(:exist?).returns(false)
inspec.expects(:command).with('timeout 1 bash -c "< /dev/tcp/example.com/1234"').returns(command_response)
provider.ping("example.com", "1234", "tcp")
end
it "uses bash if netcat not available on Darwin" do
nc_command.stubs(:exist?).returns(false)
inspec.expects(:command).with('gtimeout 1 bash -c "< /dev/tcp/example.com/1234"').returns(command_response)
darwin_provider = Inspec::Resources::DarwinHostProvider.new(inspec)
darwin_provider.ping("example.com", "1234", "tcp")
end
end
describe "#missing_requirements" do
describe "bash with net redirects and no netcat" do
before do
strings_command.stubs(:exit_status).returns(0)
nc_command.stubs(:exist?).returns(false)
ncat_command.stubs(:exist?).returns(false)
end
it "returns an empty array if timeout is available" do
timeout_command.stubs(:exist?).returns(true)
_(provider.missing_requirements("tcp")).must_equal([])
end
it "returns a missing requirement when timeout is missing" do
timeout_command.stubs(:exist?).returns(false)
_(provider.missing_requirements("tcp")).must_equal(["timeout (part of coreutils) or netcat must be installed"])
end
end
describe "bash without net redirects" do
before do
strings_command.stubs(:exit_status).returns(1)
end
it "returns an empty array if nc is installed but ncat is not installed" do
nc_command.stubs(:exist?).returns(true)
ncat_command.stubs(:exist?).returns(false)
_(provider.missing_requirements("tcp")).must_equal([])
end
it "returns an empty array if nc is not installed but ncat is installed" do
nc_command.stubs(:exist?).returns(false)
ncat_command.stubs(:exist?).returns(true)
_(provider.missing_requirements("tcp")).must_equal([])
end
it "returns an empty array if both nc and ncat are installed" do
nc_command.stubs(:exist?).returns(true)
ncat_command.stubs(:exist?).returns(true)
_(provider.missing_requirements("tcp")).must_equal([])
end
it "returns a missing requirement when neither nc nor ncat are installed" do
nc_command.stubs(:exist?).returns(false)
ncat_command.stubs(:exist?).returns(false)
_(provider.missing_requirements("tcp")).must_equal(["netcat must be installed"])
end
end
end
describe "#netcat_check_command" do
before do
strings_command.stubs(:exit_status).returns(1)
end
it "returns an nc command when nc exists tcp" do
nc_command.expects(:exist?).returns(true)
ncat_command.expects(:exist?).returns(false)
_(provider.netcat_check_command("foo", 1234, "tcp")).must_equal "echo | nc -v -w 1 foo 1234"
end
it "returns an nc command when nc exists udp" do
nc_command.expects(:exist?).returns(true)
ncat_command.expects(:exist?).returns(false)
_(provider.netcat_check_command("foo", 1234, "udp")).must_equal "echo | nc -v -w 1 -u foo 1234"
end
it "returns an ncat command when nc does not exist but ncat exists tcp" do
nc_command.expects(:exist?).returns(false)
ncat_command.expects(:exist?).returns(true)
_(provider.netcat_check_command("foo", 1234, "tcp")).must_equal "echo | ncat -v -w 1 foo 1234"
end
it "returns an ncat command when nc does not exist but ncat exists udp" do
nc_command.expects(:exist?).returns(false)
ncat_command.expects(:exist?).returns(true)
_(provider.netcat_check_command("foo", 1234, "udp")).must_equal "echo | ncat -v -w 1 -u foo 1234"
end
it "returns nil if neither nc or ncat exist" do
nc_command.expects(:exist?).returns(false)
ncat_command.expects(:exist?).returns(false)
_(provider.netcat_check_command("foo", 1234, "tcp")).must_be_nil
end
end
end