make command.exist? POSIX conform

With the current implementation, on a Linux system without bash
command.exist? always returns false. 'sh -c' is guaranteed to exist on a
POSIX-conform system [1] whereas 'bash -c' only works if bash is
actually installed.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html

Obvious fix.
This commit is contained in:
Raimar Sandner 2020-01-01 16:02:53 +01:00
parent 1f77cb1369
commit fa2f2c2caa
5 changed files with 23 additions and 23 deletions

View file

@ -67,7 +67,7 @@ module Inspec::Resources
res = if inspec.platform.name == "alpine"
inspec.backend.run_command("which \"#{@command}\"")
else
inspec.backend.run_command("bash -c 'type \"#{@command}\"'")
inspec.backend.run_command("sh -c 'type \"#{@command}\"'")
end
elsif inspec.os.windows?
res = inspec.backend.run_command("Get-Command \"#{@command}\"")

View file

@ -193,12 +193,12 @@ class MockLoader
"" => empty.call,
"sh -c 'find /no/such/mock -type f -maxdepth 1'" => empty.call,
'type "brew"' => empty.call,
'bash -c \'type "pip"\'' => empty.call,
'bash -c \'type "/test/path/pip"\'' => empty.call,
'bash -c \'type "Rscript"\'' => empty.call,
'bash -c \'type "perl"\'' => empty.call,
'bash -c \'type "/sbin/auditctl"\'' => empty.call,
'bash -c \'type "sql"\'' => cmd_exit_1.call,
'sh -c \'type "pip"\'' => empty.call,
'sh -c \'type "/test/path/pip"\'' => empty.call,
'sh -c \'type "Rscript"\'' => empty.call,
'sh -c \'type "perl"\'' => empty.call,
'sh -c \'type "/sbin/auditctl"\'' => empty.call,
'sh -c \'type "sql"\'' => cmd_exit_1.call,
'type "pwsh"' => empty.call,
'type "netstat"' => empty.call,
"sh -c 'find /etc/apache2/ports.conf -type l -maxdepth 1'" => empty.call,
@ -245,7 +245,7 @@ class MockLoader
"Get-Package -Name 'Mozilla Firefox' | ConvertTo-Json" => cmd.call("get-package-firefox"),
"Get-Package -Name 'Ruby 2.1.6-p336-x64' | ConvertTo-Json" => cmd.call("get-package-ruby"),
'Get-Command "choco"' => empty.call,
'bash -c \'type "choco"\'' => cmd_exit_1.call,
'sh -c \'type "choco"\'' => cmd_exit_1.call,
'(choco list --local-only --exact --include-programs --limit-output \'nssm\') -Replace "\|", "=" | ConvertFrom-StringData | ConvertTo-JSON' => cmd.call("choco-list-nssm"),
'(choco list --local-only --exact --include-programs --limit-output \'git\') -Replace "\|", "=" | ConvertFrom-StringData | ConvertTo-JSON' => empty.call,
"New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name 'dhcp'| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq 'dhcp' -or $_.DisplayName -eq 'dhcp'} | Select-Object -Property StartMode, StartName) -PassThru | ConvertTo-Json" => cmd.call("get-service-dhcp"),
@ -330,10 +330,10 @@ class MockLoader
"find /etc/apt/ -name *.list -exec sh -c 'cat {} || echo -n' \\;" => cmd.call("etc-apt"),
# iptables
"/usr/sbin/iptables -S" => cmd.call("iptables-s"),
%{bash -c 'type "/usr/sbin/iptables"'} => empty.call,
%{sh -c 'type "/usr/sbin/iptables"'} => empty.call,
# ip6tables
"/usr/sbin/ip6tables -S" => cmd.call("ip6tables-s"),
%{bash -c 'type "/usr/sbin/ip6tables"'} => empty.call,
%{sh -c 'type "/usr/sbin/ip6tables"'} => empty.call,
# apache_conf
"sh -c 'find /etc/apache2/ports.conf -type f -maxdepth 1'" => cmd.call("find-apache2-ports-conf"),
"sh -c 'find /etc/httpd/conf.d/*.conf -type f -maxdepth 1'" => cmd.call("find-httpd-ssl-conf"),
@ -426,9 +426,9 @@ class MockLoader
# get-process cmdlet for processes resource
'$Proc = Get-Process -IncludeUserName | Where-Object {$_.Path -ne $null } | Select-Object PriorityClass,Id,CPU,PM,VirtualMemorySize,NPM,SessionId,Responding,StartTime,TotalProcessorTime,UserName,Path | ConvertTo-Csv -NoTypeInformation;$Proc.Replace("""","").Replace("`r`n","`n")' => cmd.call("get-process_processes"),
# host resource: TCP/UDP reachability check on linux
%{bash -c 'type "nc"'} => empty.call,
%{bash -c 'type "ncat"'} => empty.call,
%{bash -c 'type "timeout"'} => empty.call,
%{sh -c 'type "nc"'} => empty.call,
%{sh -c 'type "ncat"'} => empty.call,
%{sh -c 'type "timeout"'} => empty.call,
%{strings `which bash` | grep -qE '/dev/(tcp|udp)/'} => empty.call,
%{echo | nc -v -w 1 -u example.com 1234} => empty.call,
%{echo | nc -v -w 1 example.com 1234} => empty.call,
@ -444,10 +444,10 @@ class MockLoader
# host resource: test-netconnection for reachability check on windows
"Test-NetConnection -ComputerName microsoft.com -WarningAction SilentlyContinue -RemotePort 1234| Select-Object -Property ComputerName, TcpTestSucceeded, PingSucceeded | ConvertTo-Json" => cmd.call("Test-NetConnection"),
# postgres tests
%q{bash -c 'type "psql"'} => cmd.call("bash -c type psql"),
%q{sh -c 'type "psql"'} => cmd.call("sh -c type psql"),
%q(psql --version | awk '{ print $NF }' | awk -F. '{ print $1"."$2 }') => cmd.call("psql-version"),
# mssql tests
"bash -c 'type \"sqlcmd\"'" => cmd.call("mssql-sqlcmd"),
"sh -c 'type \"sqlcmd\"'" => cmd.call("mssql-sqlcmd"),
"cb0efcd12206e9690c21ac631a72be9dd87678aa048e6dae16b8e9353ab6dd64" => cmd.call("mssql-getdate"),
"7109e5d809058cd3e9cad108e21e91234d2638db4a4f81fadfde21e071a423dc" => cmd.call("mssql-getdate"),
"5c2bc0f0568d11451d6cf83aff02ee3d47211265b52b6c5d45f8e57290b35082" => cmd.call("mssql-getdate"),
@ -458,12 +458,12 @@ class MockLoader
"4b550bb227058ac5851aa0bc946be794ee46489610f17842700136cf8bb5a0e9" => cmd.call("mssql-getdate"),
"7d1a7a0f2bd1e7da9a6904e1f28981146ec01a0323623e12a8579d30a3960a79" => cmd.call("mssql-result"),
# oracle
"bash -c 'type \"sqlplus\"'" => cmd.call("oracle-cmd"),
"sh -c 'type \"sqlplus\"'" => cmd.call("oracle-cmd"),
"1998da5bc0f09bd5258fad51f45447556572b747f631661831d6fcb49269a448" => cmd.call("oracle-result"),
# nginx mock cmd
%{nginx -V 2>&1} => cmd.call("nginx-v"),
%{/usr/sbin/nginx -V 2>&1} => cmd.call("nginx-v"),
%{bash -c 'type "/usr/sbin/nginx"'} => cmd.call("bash-c-type-nginx"),
%{sh -c 'type "/usr/sbin/nginx"'} => cmd.call("sh-c-type-nginx"),
# needed for two differnt inspec.command call formats
# host resource: dig commands,
"dig +short A example.com" => cmd.call("dig-A-example.com"),
@ -483,7 +483,7 @@ class MockLoader
"firewall-cmd --zone=public --list-sources" => cmd.call("firewall-cmd-sources-bound"),
"firewall-cmd --zone=default --list-sources" => cmd.call("firewall-cmd-sources-bound"),
"firewall-cmd --zone=public --query-rich-rule=rule family=ipv4 source address=192.168.0.14 accept" => cmd.call("firewall-cmd-has-rule-enabled"),
"bash -c 'type \"firewall-cmd\"'" => cmd.call("firewall-cmd"),
"sh -c 'type \"firewall-cmd\"'" => cmd.call("firewall-cmd"),
"rpm -qia firewalld" => cmd.call("pkg-info-firewalld"),
"systemctl is-active sshd --quiet" => empty.call,
"systemctl is-active apache2 --quiet" => empty.call,
@ -499,7 +499,7 @@ class MockLoader
'type "lsof"' => empty.call,
"test -f /etc/mysql/debian.cnf && cat /etc/mysql/debian.cnf" => empty.call,
# http resource - remote worker'
%{bash -c 'type "curl"'} => cmd.call("bash-c-type-curl"),
%{sh -c 'type "curl"'} => cmd.call("sh-c-type-curl"),
"curl -i -X GET --connect-timeout 60 --max-time 120 'http://www.example.com'" => cmd.call("http-remote-no-options"),
"curl -i -X GET --connect-timeout 60 --max-time 120 --location --max-redirs 1 'http://www.example.com'" => cmd.call("http-remote-max-redirs"),
"curl -i -X GET --connect-timeout 60 --max-time 120 --user 'user:pass' 'http://www.example.com'" => cmd.call("http-remote-basic-auth"),
@ -546,8 +546,8 @@ class MockLoader
if @platform && @platform[:name] == "alpine"
mock_cmds.merge!(
"ps --help" => cmd_stderr.call("ps-help-busybox"),
%{bash -c 'type "netstat"'} => cmd_exit_1.call,
%{bash -c 'type "ss"'} => cmd_exit_1.call,
%{sh -c 'type "netstat"'} => cmd_exit_1.call,
%{sh -c 'type "ss"'} => cmd_exit_1.call,
%{which "ss"} => cmd_exit_1.call,
%{which "netstat"} => empty.call,
"netstat -tulpen" => cmd.call("netstat-tulpen-busybox")
@ -555,8 +555,8 @@ class MockLoader
else
mock_cmds.merge!(
"ps --help" => empty.call,
%{bash -c 'type "ss"'} => empty.call,
%{bash -c 'type "netstat"'} => empty.call,
%{sh -c 'type "ss"'} => empty.call,
%{sh -c 'type "netstat"'} => empty.call,
"ss -tulpen" => cmd.call("ss-tulpen"),
"netstat -tulpen" => cmd.call("netstat-tulpen")
)