mirror of
https://github.com/inspec/inspec
synced 2024-11-10 07:04:15 +00:00
Update ssh_config resource to support returning the current sshd_config file in use. (#7070)
* modify resource * windows compatibility * end line * removing comments to clean things up Signed-off-by: Aaron Lippold <lippold@gmail.com> * CHEF-12175: Remove use of `Kernel.open` or `IO.read` or similar sinks with a non-constant value (#7079) * fix: update io reads to fix codescanning vuln Signed-off-by: Sonu Saha <sonu.saha@progress.com> * fix: remove kernel#open fallback and update open method to handle local files Signed-off-by: Sonu Saha <sonu.saha@progress.com> * fix: replace io.readlines to file.readlines Signed-off-by: Sonu Saha <sonu.saha@progress.com> * chore: fix lint offense, unnecessary space Signed-off-by: Sonu Saha <sonu.saha@progress.com> * fix: raise exception for standard errors as FetcherFailure Signed-off-by: Sonu Saha <sonu.saha@progress.com> * chore: update exception message Signed-off-by: Sonu Saha <sonu.saha@progress.com> --------- Signed-off-by: Sonu Saha <sonu.saha@progress.com> * fix: Missing regular expression anchor (#7077) Signed-off-by: Sonu Saha <sonu.saha@progress.com> * Bump version to 6.6.27 by Chef Expeditor Obvious fix; these changes are the result of automation not creative thinking. * Fix gitignore file in docs dir (#7082) Signed-off-by: Ian Maddaus <ian.maddaus@progress.com> * Bump version to 6.6.28 by Chef Expeditor Obvious fix; these changes are the result of automation not creative thinking. * adding docs now that the gitignore is fixed. Signed-off-by: Aaron Lippold <lippold@gmail.com> * add docs for sshd_active_config resource * fix docs * unit tests * rubocop on ssh_config.rb, sshd_con_test.rb, and sshd_active_config.md * rename active path in method * doc fix * Linting Corrections for Active SSHD Config (#1) Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Update sshd_active_config.md updated version * doc version update --------- Signed-off-by: Aaron Lippold <lippold@gmail.com> Signed-off-by: Sonu Saha <sonu.saha@progress.com> Signed-off-by: Ian Maddaus <ian.maddaus@progress.com> Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> Co-authored-by: Daniel Medina <dmedina@mitre.org> Co-authored-by: Sonu Saha <98935583+ahasunos@users.noreply.github.com> Co-authored-by: Chef Expeditor <chef-ci@chef.io> Co-authored-by: Ian Maddaus <IanMadd@users.noreply.github.com> Co-authored-by: Clinton Wolfe <clintoncwolfe@gmail.com>
This commit is contained in:
parent
0e904a32bf
commit
0ab35681aa
5 changed files with 216 additions and 11 deletions
|
@ -21,7 +21,7 @@ Use the `ssh_config` Chef InSpec audit resource to test OpenSSH client configura
|
|||
|
||||
### Version
|
||||
|
||||
This resource first became available in v1.0.0 of InSpec.
|
||||
This resource first became available in v6.8.0 of InSpec.
|
||||
|
||||
## Syntax
|
||||
|
||||
|
|
99
docs-chef-io/content/inspec/resources/sshd_active_config.md
Normal file
99
docs-chef-io/content/inspec/resources/sshd_active_config.md
Normal file
|
@ -0,0 +1,99 @@
|
|||
+++
|
||||
title = "sshd_active_config resource"
|
||||
draft = false
|
||||
gh_repo = "inspec"
|
||||
platform = "linux"
|
||||
[menu]
|
||||
[menu.inspec]
|
||||
title = "sshd_active_config"
|
||||
identifier = "inspec/resources/os/sshd_active_config.md sshd_active_config resource"
|
||||
parent = "inspec/resources/os"
|
||||
+++
|
||||
Use the `sshd_active_config` Chef InSpec audit resource to find and test configuration data for the OpenSSH daemon. By default, this configuration data is located at `/etc/ssh/sshd_config` on Linux and Unix platforms. However, this resource is designed to retrieve the active configuration file by the sshd process itself. sshd---the OpenSSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command execution, and data exchanges.
|
||||
## Availability
|
||||
|
||||
### Install
|
||||
|
||||
{{< readfile file="content/inspec/reusable/md/inspec_installation.md" >}}
|
||||
|
||||
### Version
|
||||
|
||||
This resource first became available in v6.8.0 of InSpec.
|
||||
|
||||
## Syntax
|
||||
|
||||
An `sshd_active_config` resource block declares the OpenSSH daemon configuration data to be tested:
|
||||
|
||||
describe sshd_active_config do
|
||||
its('name') { should include('foo') }
|
||||
end
|
||||
|
||||
where
|
||||
|
||||
- `name` is a configuration setting in `sshd_config`
|
||||
- `{ should include('foo') }` tests the value of `name` as read from `sshd_active_config` versus the value declared in the test
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples show how to use this Chef InSpec audit resource.
|
||||
|
||||
### Inspect the file and path found by the `sshd_active_config` resource
|
||||
|
||||
describe sshd_active_config.active_path do
|
||||
it { should match '/expected/path/sshd_config' }
|
||||
end
|
||||
|
||||
### Test which variables may be sent to the server
|
||||
|
||||
describe sshd_active_config do
|
||||
its('AcceptEnv') { should include('CI_ENABLE_COVERAGE') }
|
||||
end
|
||||
|
||||
### Test for IPv6-only addresses
|
||||
|
||||
describe sshd_active_config do
|
||||
its('AddressFamily') { should cmp 'inet6' }
|
||||
end
|
||||
|
||||
### Test the Protocol setting
|
||||
|
||||
describe sshd_active_config do
|
||||
its('Protocol') { should cmp 2 }
|
||||
end
|
||||
|
||||
### Test for approved, strong ciphers
|
||||
|
||||
describe sshd_active_config do
|
||||
its('Ciphers') { should cmp('chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr') }
|
||||
end
|
||||
|
||||
### Test SSH protocols
|
||||
|
||||
describe sshd_active_config do
|
||||
its('Port') { should cmp 22 }
|
||||
its('UsePAM') { should eq 'yes' }
|
||||
its('ListenAddress') { should eq nil }
|
||||
its('HostKey') do
|
||||
should eq [
|
||||
'/etc/ssh/ssh_host_rsa_key',
|
||||
'/etc/ssh/ssh_host_dsa_key',
|
||||
'/etc/ssh/ssh_host_ecdsa_key',
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
## Matchers
|
||||
|
||||
{{< readfile file="content/inspec/reusable/md/inspec_matchers_link.md" >}}
|
||||
|
||||
This resource has the following special matchers.
|
||||
|
||||
### name
|
||||
|
||||
The `name` matcher tests the value of `name` as read from `sshd_active_config` versus the value declared in the test:
|
||||
|
||||
its('name') { should cmp 'foo' }
|
||||
|
||||
or:
|
||||
|
||||
its('name') {should include('bar') }
|
|
@ -38,16 +38,13 @@ module Inspec::Resources
|
|||
|
||||
def convert_hash(hash)
|
||||
new_hash = {}
|
||||
hash.each do |k, v|
|
||||
new_hash[k.downcase] ||= v
|
||||
end
|
||||
hash.each { |k, v| new_hash[k.downcase] ||= v }
|
||||
new_hash
|
||||
end
|
||||
|
||||
def method_missing(name)
|
||||
param = read_params[name.to_s.downcase]
|
||||
return nil if param.nil?
|
||||
# extract first value if we have only one value in array
|
||||
return param[0] if param.length == 1
|
||||
|
||||
param
|
||||
|
@ -73,11 +70,12 @@ module Inspec::Resources
|
|||
return @params if defined?(@params)
|
||||
return @params = {} if read_content.nil?
|
||||
|
||||
conf = SimpleConfig.new(
|
||||
read_content,
|
||||
assignment_regex: /^\s*(\S+?)\s+(.*?)\s*$/,
|
||||
multiple_values: true
|
||||
)
|
||||
conf =
|
||||
SimpleConfig.new(
|
||||
read_content,
|
||||
assignment_regex: /^\s*(\S+?)\s+(.*?)\s*$/,
|
||||
multiple_values: true
|
||||
)
|
||||
@params = convert_hash(conf.params)
|
||||
end
|
||||
|
||||
|
@ -121,4 +119,97 @@ module Inspec::Resources
|
|||
"/etc/ssh/#{type}"
|
||||
end
|
||||
end
|
||||
|
||||
class SshdActiveConfig < SshdConfig
|
||||
name "sshd_active_config"
|
||||
supports platform: "unix"
|
||||
supports platform: "windows"
|
||||
desc "Use the sshd_active_config InSpec audit resource to test configuration data for the Open SSH daemon located at /etc/ssh/sshd_config on Linux and UNIX platforms. sshd---the Open SSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command execution, and data exchanges."
|
||||
example <<~EXAMPLE
|
||||
describe sshd_active_config do
|
||||
its('Protocol') { should eq '2' }
|
||||
end
|
||||
EXAMPLE
|
||||
|
||||
attr_reader :active_path
|
||||
|
||||
def initialize
|
||||
@active_path = dynamic_sshd_config_path
|
||||
super(@active_path)
|
||||
end
|
||||
|
||||
def to_s
|
||||
"SSHD Active Configuration (active path: #{@conf_path})"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ssh_config_file(type)
|
||||
if inspec.os.windows?
|
||||
programdata = inspec.os_env("programdata").content
|
||||
return "#{programdata}\\ssh\\#{type}"
|
||||
end
|
||||
|
||||
"/etc/ssh/#{type}"
|
||||
end
|
||||
|
||||
def dynamic_sshd_config_path
|
||||
if inspec.os.windows?
|
||||
script = <<-EOH
|
||||
$sshdPath = (Get-Command sshd.exe).Source
|
||||
if ($sshdPath -ne $null) {
|
||||
Write-Output $sshdPath
|
||||
} else {
|
||||
Write-Error "sshd.exe not found"
|
||||
}
|
||||
EOH
|
||||
sshd_path_result = inspec.powershell(script).stdout.strip
|
||||
sshd_path = "\"#{sshd_path_result}\""
|
||||
if !sshd_path_result.empty? && sshd_path_result != "sshd.exe not found"
|
||||
command_output = inspec.command("sudo #{sshd_path} -dd 2>&1").stdout
|
||||
dynamic_path =
|
||||
command_output
|
||||
.lines
|
||||
.find { |line| line.include?("filename") }
|
||||
&.split("filename")
|
||||
&.last
|
||||
&.strip
|
||||
env_var_name = dynamic_path.match(/__(.*?)__/)[1]
|
||||
if env_var_name?
|
||||
dynamic_path =
|
||||
dynamic_path.gsub(
|
||||
/__#{env_var_name}__/,
|
||||
inspec.os_env(env_var_name).content
|
||||
)
|
||||
end
|
||||
else
|
||||
Inspec::Log.error("sshd.exe not found using PowerShell script block.")
|
||||
return nil
|
||||
end
|
||||
elsif inspec.os.unix?
|
||||
sshd_path = "/usr/sbin/sshd"
|
||||
command_output = inspec.command("sudo #{sshd_path} -dd 2>&1").stdout
|
||||
dynamic_path =
|
||||
command_output
|
||||
.lines
|
||||
.find { |line| line.include?("filename") }
|
||||
&.split("filename")
|
||||
&.last
|
||||
&.strip
|
||||
else
|
||||
Inspec::Log.error(
|
||||
"Unable to determine sshd configuration path on Windows using -T flag."
|
||||
)
|
||||
return nil
|
||||
end
|
||||
|
||||
if dynamic_path.nil? || dynamic_path.empty?
|
||||
Inspec::Log.warn(
|
||||
"No active SSHD configuration found. Using default configuration."
|
||||
)
|
||||
return ssh_config_file("sshd_config")
|
||||
end
|
||||
dynamic_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
2
lib/inspec/resources/sshd_active_config.rb
Normal file
2
lib/inspec/resources/sshd_active_config.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
# This is just here to make the dynamic loader happy.
|
||||
require "inspec/resources/ssh_config"
|
|
@ -3,7 +3,6 @@ require "inspec/resource"
|
|||
require "inspec/resources/ssh_config"
|
||||
|
||||
describe "Inspec::Resources::SshConfig" do
|
||||
|
||||
describe "ssh_config" do
|
||||
it "check ssh config parsing" do
|
||||
resource = load_resource("ssh_config")
|
||||
|
@ -48,4 +47,18 @@ describe "Inspec::Resources::SshConfig" do
|
|||
_(resource.resource_exception_message).must_equal "File is empty: /etc/ssh/sshd_config_empty"
|
||||
end
|
||||
end
|
||||
|
||||
describe "sshd_active_config" do
|
||||
it "check protocol version" do
|
||||
resource = load_resource("sshd_active_config")
|
||||
_(resource.Port).must_equal "22"
|
||||
_(resource.UsePAM).must_equal "yes"
|
||||
_(resource.ListenAddress).must_be_nil
|
||||
_(resource.HostKey).must_equal [
|
||||
"/etc/ssh/ssh_host_rsa_key",
|
||||
"/etc/ssh/ssh_host_dsa_key",
|
||||
"/etc/ssh/ssh_host_ecdsa_key",
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue