From 865dd145774231e743dd082dffa459ad59f985a5 Mon Sep 17 00:00:00 2001 From: Jonathan Metzger <9845417+jrmetzger@users.noreply.github.com> Date: Mon, 13 Jan 2025 15:38:31 -0500 Subject: [PATCH 01/17] Update for 8.10 Tested against 8.10. Regex for 8.1 and fails test. Should add End of Line for regex to differ 8.1 with 8.10 --- controls/SV-230221.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/SV-230221.rb b/controls/SV-230221.rb index ffcb287..25f3a1c 100644 --- a/controls/SV-230221.rb +++ b/controls/SV-230221.rb @@ -51,7 +51,7 @@ release = os.release EOMS_DATE = { - /^8\.1/ => '30 November 2021', + /^8\.1$/ => '30 November 2021', /^8\.2/ => '30 April 2022', /^8\.3/ => '30 April 2021', /^8\.4/ => '31 May 2023', From 50a0b9522e2e3108bc972df1b4e3f4236b00eb0f Mon Sep 17 00:00:00 2001 From: Jonathan Metzger <9845417+jrmetzger@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:21:35 -0500 Subject: [PATCH 02/17] Update inspec.yml bump inspec version --- inspec.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inspec.yml b/inspec.yml index 88a46c5..3f99794 100644 --- a/inspec.yml +++ b/inspec.yml @@ -4,7 +4,7 @@ maintainer: MITRE SAF Team copyright: MITRE license: Apache-2.0 summary: "This Security Technical Implementation Guide is published as a tool to improve the security of Department of Defense (DoD) information systems. The requirements are derived from the National Institute of Standards and Technology (NIST) 800-53 and related documents. Comments or proposed revisions to this document should be sent via email to the following address: disa.stig_spt@mail.mil." -version: 1.14.1 +version: 1.14.2 inspec_version: ">= 5.0" @@ -1047,4 +1047,4 @@ inputs: type: String value: 'local' - \ No newline at end of file + From a11582387c19bcdc3d591bea44d65a51b42242e5 Mon Sep 17 00:00:00 2001 From: Jon Metzger Date: Fri, 17 Jan 2025 16:10:34 -0500 Subject: [PATCH 03/17] fix version --- Rakefile | 2 +- controls/SV-230221.rb | 18 +++++++++--------- controls/SV-230332.rb | 2 +- controls/SV-230338.rb | 6 +++--- controls/SV-230342.rb | 6 +++--- controls/SV-230344.rb | 6 +++--- controls/SV-230475.rb | 4 ++-- controls/SV-250316.rb | 6 +++--- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Rakefile b/Rakefile index 139a368..14494ea 100755 --- a/Rakefile +++ b/Rakefile @@ -14,7 +14,7 @@ end begin RuboCop::RakeTask.new(:lint) do |task| - task.options += %w[--display-cop-names --no-color --parallel] + task.options += %w(--display-cop-names --no-color --parallel) end rescue LoadError puts 'rubocop is not available. Install the rubocop gem to run the lint tests.' diff --git a/controls/SV-230221.rb b/controls/SV-230221.rb index 25f3a1c..c352474 100644 --- a/controls/SV-230221.rb +++ b/controls/SV-230221.rb @@ -52,15 +52,15 @@ EOMS_DATE = { /^8\.1$/ => '30 November 2021', - /^8\.2/ => '30 April 2022', - /^8\.3/ => '30 April 2021', - /^8\.4/ => '31 May 2023', - /^8\.5/ => '31 May 2022', - /^8\.6/ => '31 May 2024', - /^8\.7/ => '31 May 2023', - /^8\.8/ => '31 May 2025', - /^8\.9/ => '31 May 2024', - /^8\.10/ => '31 May 2029' + /^8\.2$/ => '30 April 2022', + /^8\.3$/ => '30 April 2021', + /^8\.4$/ => '31 May 2023', + /^8\.5$/ => '31 May 2022', + /^8\.6$/ => '31 May 2024', + /^8\.7$/ => '31 May 2023', + /^8\.8$/ => '31 May 2025', + /^8\.9$/ => '31 May 2024', + /^8\.10$/ => '31 May 2029' }.find { |k, _v| k.match(release) }&.last describe "The release \"#{release}\" is still be within the support window" do diff --git a/controls/SV-230332.rb b/controls/SV-230332.rb index f393b33..3f307b5 100644 --- a/controls/SV-230332.rb +++ b/controls/SV-230332.rb @@ -87,7 +87,7 @@ !input('central_account_management') } - if os.release.to_f >= 8.2 + if Gem::Version.new(os.release) < Gem::Version.new('8.2') impact 0.0 describe 'This requirement only applies to RHEL 8 version(s) 8.0 and 8.1' do skip "Currently on release #{os.release}, this control is Not Applicable." diff --git a/controls/SV-230338.rb b/controls/SV-230338.rb index 0bc95ed..f06b5cd 100644 --- a/controls/SV-230338.rb +++ b/controls/SV-230338.rb @@ -76,9 +76,9 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.0 and 8.1, if the system is RHEL version 8.2 or newer, this check is not applicable.', impact: 0.0) { - (os.release.to_f) < 8.2 - } + only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do + Gem::Version.new(os.release) < Gem::Version.new('8.2') + end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230342.rb b/controls/SV-230342.rb index 3ad7b61..6134046 100644 --- a/controls/SV-230342.rb +++ b/controls/SV-230342.rb @@ -75,9 +75,9 @@ tag cci: ['CCI-000044'] tag nist: ['AC-7 a'] - only_if('If the system is RHEL version 8.2 or newer, this check is not applicable.', impact: 0.0) { - (os.release.to_f) < 8.2 - } + only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do + Gem::Version.new(os.release) < Gem::Version.new('8.2') + end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230344.rb b/controls/SV-230344.rb index b26797b..8ec1ed2 100644 --- a/controls/SV-230344.rb +++ b/controls/SV-230344.rb @@ -79,9 +79,9 @@ tag 'host' tag 'container' - only_if('If the system is RHEL version 8.2 or newer, this check is not applicable.', impact: 0.0) { - (os.release.to_f) < 8.2 - } + only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do + Gem::Version.new(os.release) < Gem::Version.new('8.2') + end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230475.rb b/controls/SV-230475.rb index 2e2b1d9..0351d62 100644 --- a/controls/SV-230475.rb +++ b/controls/SV-230475.rb @@ -62,13 +62,13 @@ !virtualization.system.eql?('docker') } - audit_tools = %w[/usr/sbin/auditctl + audit_tools = %w(/usr/sbin/auditctl /usr/sbin/auditd /usr/sbin/ausearch /usr/sbin/aureport /usr/sbin/autrace /usr/sbin/rsyslogd - /usr/sbin/augenrules] + /usr/sbin/augenrules) if package('aide').installed? audit_tools.each do |tool| diff --git a/controls/SV-250316.rb b/controls/SV-250316.rb index 4bc5b30..a269f15 100644 --- a/controls/SV-250316.rb +++ b/controls/SV-250316.rb @@ -65,9 +65,9 @@ module with the following command: tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) { - os.release.to_f < 8.2 - } + only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do + Gem::Version.new(os.release) < Gem::Version.new('8.2') + end describe selinux do it { should be_installed } From 288b02e58cca6bc8c82b681d58d63ec201637eb8 Mon Sep 17 00:00:00 2001 From: Jonathan Metzger <9845417+jrmetzger@users.noreply.github.com> Date: Fri, 17 Jan 2025 16:12:41 -0500 Subject: [PATCH 04/17] Update controls/SV-230342.rb --- controls/SV-230342.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/SV-230342.rb b/controls/SV-230342.rb index 6134046..99588fd 100644 --- a/controls/SV-230342.rb +++ b/controls/SV-230342.rb @@ -76,7 +76,7 @@ tag nist: ['AC-7 a'] only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do - Gem::Version.new(os.release) < Gem::Version.new('8.2') + Gem::Version.new(os.release) <= Gem::Version.new('8.2') end pam_auth_files = input('pam_auth_files') From 6456c0eb6c01d2caf794268f26f4a57d5e445869 Mon Sep 17 00:00:00 2001 From: Jonathan Metzger <9845417+jrmetzger@users.noreply.github.com> Date: Fri, 17 Jan 2025 16:13:14 -0500 Subject: [PATCH 05/17] Update controls/SV-230342.rb --- controls/SV-230342.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/SV-230342.rb b/controls/SV-230342.rb index 99588fd..c95493b 100644 --- a/controls/SV-230342.rb +++ b/controls/SV-230342.rb @@ -75,7 +75,7 @@ tag cci: ['CCI-000044'] tag nist: ['AC-7 a'] - only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do + only_if('This check applies to RHEL versions 8.0, 8.1 and 8.2. If the system is RHEL version 8.3 or newer, this check is Not Applicable.', impact: 0.0) do Gem::Version.new(os.release) <= Gem::Version.new('8.2') end From f48bc7afe814ae4d9b7b2b83719165e1435d4ba4 Mon Sep 17 00:00:00 2001 From: Jon Metzger Date: Fri, 17 Jan 2025 16:40:22 -0500 Subject: [PATCH 06/17] fix --- controls/SV-230338.rb | 2 +- controls/SV-230342.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/controls/SV-230338.rb b/controls/SV-230338.rb index f06b5cd..1f82010 100644 --- a/controls/SV-230338.rb +++ b/controls/SV-230338.rb @@ -76,7 +76,7 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do + only_if('This check applies to RHEL versions 8.0 or 8.1. If the system is RHEL version 8.3 or newer, this check is Not Applicable.', impact: 0.0) do Gem::Version.new(os.release) < Gem::Version.new('8.2') end diff --git a/controls/SV-230342.rb b/controls/SV-230342.rb index c95493b..d02cd7e 100644 --- a/controls/SV-230342.rb +++ b/controls/SV-230342.rb @@ -75,8 +75,8 @@ tag cci: ['CCI-000044'] tag nist: ['AC-7 a'] - only_if('This check applies to RHEL versions 8.0, 8.1 and 8.2. If the system is RHEL version 8.3 or newer, this check is Not Applicable.', impact: 0.0) do - Gem::Version.new(os.release) <= Gem::Version.new('8.2') + only_if('This check applies to RHEL versions 8.0 or 8.1. If the system is RHEL version 8.3 or newer, this check is Not Applicable.', impact: 0.0) do + Gem::Version.new(os.release) < Gem::Version.new('8.2') end pam_auth_files = input('pam_auth_files') From 3054e865d955e2ee4b152442f6fcc47609211b49 Mon Sep 17 00:00:00 2001 From: Jon Metzger Date: Fri, 17 Jan 2025 16:41:06 -0500 Subject: [PATCH 07/17] fix --- controls/SV-230332.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/SV-230332.rb b/controls/SV-230332.rb index 3f307b5..fb317cd 100644 --- a/controls/SV-230332.rb +++ b/controls/SV-230332.rb @@ -87,7 +87,7 @@ !input('central_account_management') } - if Gem::Version.new(os.release) < Gem::Version.new('8.2') + if Gem::Version.new(os.release) > Gem::Version.new('8.2') impact 0.0 describe 'This requirement only applies to RHEL 8 version(s) 8.0 and 8.1' do skip "Currently on release #{os.release}, this control is Not Applicable." From 031a544de652c71fe783277f23d5165a2c53b854 Mon Sep 17 00:00:00 2001 From: Jon Metzger Date: Fri, 17 Jan 2025 16:41:15 -0500 Subject: [PATCH 08/17] fix operator --- controls/SV-230332.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/SV-230332.rb b/controls/SV-230332.rb index fb317cd..8d154a8 100644 --- a/controls/SV-230332.rb +++ b/controls/SV-230332.rb @@ -87,7 +87,7 @@ !input('central_account_management') } - if Gem::Version.new(os.release) > Gem::Version.new('8.2') + if Gem::Version.new(os.release) >= Gem::Version.new('8.2') impact 0.0 describe 'This requirement only applies to RHEL 8 version(s) 8.0 and 8.1' do skip "Currently on release #{os.release}, this control is Not Applicable." From 06a14cd8e5a3830096923922871749b762abb372 Mon Sep 17 00:00:00 2001 From: Aaron Lippold Date: Wed, 5 Feb 2025 23:54:54 -0500 Subject: [PATCH 09/17] updated the new controls to use the updated resource, which is in PR review Signed-off-by: Aaron Lippold --- controls/SV-230332.rb | 4 +- controls/SV-230338.rb | 7 +- controls/SV-230342.rb | 7 +- controls/SV-230344.rb | 7 +- controls/SV-250316.rb | 7 +- libraries/os.rb | 183 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 libraries/os.rb diff --git a/controls/SV-230332.rb b/controls/SV-230332.rb index 8d154a8..23f811b 100644 --- a/controls/SV-230332.rb +++ b/controls/SV-230332.rb @@ -87,10 +87,10 @@ !input('central_account_management') } - if Gem::Version.new(os.release) >= Gem::Version.new('8.2') + if os.version >= '8.2' impact 0.0 describe 'This requirement only applies to RHEL 8 version(s) 8.0 and 8.1' do - skip "Currently on release #{os.release}, this control is Not Applicable." + skip "Currently on release #{os.version}, this control is Not Applicable." end else [ diff --git a/controls/SV-230338.rb b/controls/SV-230338.rb index 1f82010..5631e7f 100644 --- a/controls/SV-230338.rb +++ b/controls/SV-230338.rb @@ -76,8 +76,11 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.0 or 8.1. If the system is RHEL version 8.3 or newer, this check is Not Applicable.', impact: 0.0) do - Gem::Version.new(os.release) < Gem::Version.new('8.2') + only_if("\n" + <<~MESSAGE, impact: 0.0) do + This check only applies to RHEL versions 8.0 or 8.1. + The system is running RHEL version: #{os.version}, this check is Not Applicable. + MESSAGE + ['8.0', '8.1'].include?(os.version) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230342.rb b/controls/SV-230342.rb index d02cd7e..9910854 100644 --- a/controls/SV-230342.rb +++ b/controls/SV-230342.rb @@ -75,8 +75,11 @@ tag cci: ['CCI-000044'] tag nist: ['AC-7 a'] - only_if('This check applies to RHEL versions 8.0 or 8.1. If the system is RHEL version 8.3 or newer, this check is Not Applicable.', impact: 0.0) do - Gem::Version.new(os.release) < Gem::Version.new('8.2') + only_if("\n" + <<~MESSAGE, impact: 0.0) do + This check only applies to RHEL versions 8.0 or 8.1. + The system is running RHEL version: #{os.version}, this check is Not Applicable. + MESSAGE + ['8.0', '8.1'].include?(os.version) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230344.rb b/controls/SV-230344.rb index 8ec1ed2..829224f 100644 --- a/controls/SV-230344.rb +++ b/controls/SV-230344.rb @@ -79,8 +79,11 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do - Gem::Version.new(os.release) < Gem::Version.new('8.2') + only_if("\n" + <<~MESSAGE, impact: 0.0) do + This check only applies to RHEL versions 8.0 or 8.1. + The system is running RHEL version: #{os.version}, this check is Not Applicable. + MESSAGE + ['8.0', '8.1'].include?(os.version) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-250316.rb b/controls/SV-250316.rb index a269f15..47249cd 100644 --- a/controls/SV-250316.rb +++ b/controls/SV-250316.rb @@ -65,8 +65,11 @@ module with the following command: tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.0 and 8.1. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) do - Gem::Version.new(os.release) < Gem::Version.new('8.2') + only_if("\n" + <<~MESSAGE, impact: 0.0) do + This check only applies to RHEL versions 8.0 or 8.1. + The system is running RHEL version: #{os.version}, this check is Not Applicable. + MESSAGE + ['8.0', '8.1'].include?(os.version) end describe selinux do diff --git a/libraries/os.rb b/libraries/os.rb new file mode 100644 index 0000000..3fec52f --- /dev/null +++ b/libraries/os.rb @@ -0,0 +1,183 @@ +require "inspec/resources/platform" +require "rubygems" unless defined?(Gem) # This provides Gem::Version + +# module Inspec +# module Resources +class OSResource < PlatformResource + name "os" + supports platform: "unix" + supports platform: "windows" + desc "Use the os InSpec audit resource to test the platform on which the system is running." + example <<~EXAMPLE + # Check OS family + describe os[:family] do + it { should eq 'redhat' } + end + + # Helper methods for specific OS families + describe os.redhat? do + it { should eq true } + end + + describe os.linux? do + it { should eq true } + end + + # Version comparisons, e.g., inspec standard `matchers` + describe os.version do + it { should cmp >= '8.10' } + end + + # Accessing version components (via symbol) + describe os.version(:major) do + it { should eq '8' } + end + + # Accessing version components (via dot accessors) + describe os.version.minor do + it { should cmp <= '10' } + end + + # Accessing version components (via string) + describe os.version('build') do + it { should eq 1234 } # Or match against nil if no build + end + + # Conditional checks based on version + if os.version <= '3.10.2' + describe file('/etc/old_config') do + it { should exist } + end + end + EXAMPLE + + # reuse helper methods from backend + %w{aix? redhat? debian? suse? bsd? solaris? linux? unix? windows? hpux? darwin?}.each do |os_family| + define_method(os_family.to_sym) do + @platform.send(os_family) + end + end + + class VersionWrapper + include Comparable + + def initialize(version_data) + @version_data = version_data + end + + def <=>(other) + @version_data[:comparable_version] <=> (other.is_a?(Gem::Version) ? other : Gem::Version.new(other.to_s)) + end + + def eql?(other) + return false unless other.is_a?(VersionWrapper) + + @version_data[:comparable_version].eql?(other.instance_variable_get(:@version_data)[:comparable_version]) + end + + def hash + @version_data[:comparable_version].hash + end + + def method_missing(method_name, *args) + return super unless respond_to_missing?(method_name) + + @version_data[method_name] + end + + def respond_to_missing?(method_name, include_private = false) + %i{major minor patch build full}.include?(method_name) || super + end + + # Updated to_s returns the original version string + # without the build if present, preserving trailing zeros. + def to_s + if @version_data[:full].present? + if @version_data[:build].present? + # For OSes like macOS that include build info, return only the base version. + @version_data[:full].split("+").first + else + # For OSes without a build, return the full string as-is. + @version_data[:full] + end + else + @version_data[:comparable_version].to_s + end + end + + def inspect + "#<#{self.class} version=\"#{self}\" major=#{major} minor=#{minor} patch=#{patch} build=\"#{build}\">" + end + + private + + def comparable_version + @version_data[:comparable_version] + end + end + + def version(component = nil) # rubocop:disable Metrics/MethodLength + @version_data ||= parse_version(normalized_version) + + return VersionWrapper.new(@version_data) if component.nil? + + # Convert string to symbol and ensure lowercase + component = component.to_s.downcase.to_sym + + case component + when :major, :minor, :patch, :build + @version_data[component] + when :full + @version_data[:full] + else + raise Inspec::Exceptions::ResourceFailed, "Unknown version component: #{component}" + end + end + + def resource_id + @platform.name || "OS" + end + + def to_s + "Operating System Detection" + end + + private + + def parse_version(version_str) + # Split version into base version and build number + base_version, build = version_str.to_s.split("+", 2) + + # Parse the base version components + major, minor, patch = base_version.strip.split(".", 3).map(&:to_i) + + # Create a clean version string for Gem::Version (without build) + comparable_version = Gem::Version.new([major, minor, patch].compact.join(".")) + + @version_data = { + comparable_version: comparable_version, # rubocop:disable Style/HashSyntax + major: major, # rubocop:disable Style/HashSyntax + minor: minor, # rubocop:disable Style/HashSyntax + patch: patch, # rubocop:disable Style/HashSyntax + build: build, # rubocop:disable Style/HashSyntax + full: version_str, + } + end + + def normalized_version + case @platform.name + when "darwin", "mac_os_x" + product_version = inspec.command("sw_vers -productVersion").stdout.strip + build_version = inspec.command("sw_vers -buildVersion").stdout.strip + "#{product_version}+#{build_version}" + when "windows" + build = inspec.registry_key('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion').value("CurrentBuild").to_s + "#{@platform.release}+#{build}" + else + @platform.release + end + end +end + +# end +# end From 535982fe81af7adca37c17bf588dfff72974b573 Mon Sep 17 00:00:00 2001 From: Aaron Lippold Date: Thu, 6 Feb 2025 00:28:04 -0500 Subject: [PATCH 10/17] updated all controls that are only applicable to 8.1 and 8.2 to use os.version Signed-off-by: Aaron Lippold --- Gemfile | 1 - Rakefile | 2 +- controls/SV-230244.rb | 2 +- controls/SV-230333.rb | 10 +++++++--- controls/SV-230334.rb | 10 +++++++--- controls/SV-230335.rb | 10 +++++++--- controls/SV-230336.rb | 10 +++++++--- controls/SV-230337.rb | 10 +++++++--- controls/SV-230338.rb | 7 ++++--- controls/SV-230339.rb | 10 +++++++--- controls/SV-230340.rb | 10 +++++++--- controls/SV-230341.rb | 10 +++++++--- controls/SV-230342.rb | 9 +++++---- controls/SV-230343.rb | 10 +++++++--- controls/SV-230344.rb | 5 +++-- controls/SV-230345.rb | 10 +++++++--- controls/SV-230475.rb | 4 ++-- controls/SV-244533.rb | 10 +++++++--- controls/SV-244534.rb | 10 +++++++--- controls/SV-250315.rb | 10 +++++++--- controls/SV-250316.rb | 5 +++-- 21 files changed, 110 insertions(+), 55 deletions(-) diff --git a/Gemfile b/Gemfile index 45b8173..b7d8e23 100644 --- a/Gemfile +++ b/Gemfile @@ -14,7 +14,6 @@ gem 'kitchen-ec2' gem 'kitchen-inspec' gem 'kitchen-sync' gem 'kitchen-vagrant' -gem 'parser', '< 3.3.1.0' gem 'rake' gem 'rubocop' gem 'rubocop-rake' diff --git a/Rakefile b/Rakefile index 14494ea..139a368 100755 --- a/Rakefile +++ b/Rakefile @@ -14,7 +14,7 @@ end begin RuboCop::RakeTask.new(:lint) do |task| - task.options += %w(--display-cop-names --no-color --parallel) + task.options += %w[--display-cop-names --no-color --parallel] end rescue LoadError puts 'rubocop is not available. Install the rubocop gem to run the lint tests.' diff --git a/controls/SV-230244.rb b/controls/SV-230244.rb index e5e900e..16356c3 100644 --- a/controls/SV-230244.rb +++ b/controls/SV-230244.rb @@ -42,7 +42,7 @@ tag 'container-conditional' only_if('SSH is not installed on the system this requirement is Not Applicable', impact: 0.0) { - (service('sshd').enabled? || package('openssh-server').installed?) + service('sshd').enabled? || package('openssh-server').installed? } client_alive_count = input('sshd_client_alive_count_max') diff --git a/controls/SV-230333.rb b/controls/SV-230333.rb index 86eb376..358d6fb 100644 --- a/controls/SV-230333.rb +++ b/controls/SV-230333.rb @@ -48,9 +48,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL version 8.2 and later. If the system is not RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe parse_config_file('/etc/security/faillock.conf') do its('deny') { should cmp <= input('unsuccessful_attempts') } diff --git a/controls/SV-230334.rb b/controls/SV-230334.rb index 90b70b2..f9de470 100644 --- a/controls/SV-230334.rb +++ b/controls/SV-230334.rb @@ -74,9 +74,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL version 8.1 and earlier. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) { - (os.release.to_f) < 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230335.rb b/controls/SV-230335.rb index 6a89fc8..4ad99c9 100644 --- a/controls/SV-230335.rb +++ b/controls/SV-230335.rb @@ -48,9 +48,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer, if the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe parse_config_file(input('security_faillock_conf')) do its('fail_interval') { should cmp >= input('fail_interval') } diff --git a/controls/SV-230336.rb b/controls/SV-230336.rb index 1703388..56494ab 100644 --- a/controls/SV-230336.rb +++ b/controls/SV-230336.rb @@ -76,9 +76,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL version 8.1 and earlier. If the system is RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) { - (os.release.to_f) < 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230337.rb b/controls/SV-230337.rb index 7e2bae3..0847904 100644 --- a/controls/SV-230337.rb +++ b/controls/SV-230337.rb @@ -50,9 +50,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer, if the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe parse_config_file('/etc/security/faillock.conf') do its('unlock_time') { should cmp >= input('lockout_time') } diff --git a/controls/SV-230338.rb b/controls/SV-230338.rb index 5631e7f..45f237e 100644 --- a/controls/SV-230338.rb +++ b/controls/SV-230338.rb @@ -76,10 +76,11 @@ tag 'host' tag 'container' - only_if("\n" + <<~MESSAGE, impact: 0.0) do - This check only applies to RHEL versions 8.0 or 8.1. - The system is running RHEL version: #{os.version}, this check is Not Applicable. + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE + only_if(message, impact: 0.0) do ['8.0', '8.1'].include?(os.version) end diff --git a/controls/SV-230339.rb b/controls/SV-230339.rb index fc70e3e..6d23dd3 100644 --- a/controls/SV-230339.rb +++ b/controls/SV-230339.rb @@ -47,9 +47,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer. If the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe parse_config_file('/etc/security/faillock.conf') do its('dir') { should cmp input('log_directory') } diff --git a/controls/SV-230340.rb b/controls/SV-230340.rb index 7fa0a11..c8fda14 100644 --- a/controls/SV-230340.rb +++ b/controls/SV-230340.rb @@ -72,9 +72,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.0 and 8.1, if the system is RHEL version 8.2 or newer, this check is not applicable.', impact: 0.0) { - (os.release.to_f) < 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230341.rb b/controls/SV-230341.rb index 4f7c40c..99a06af 100644 --- a/controls/SV-230341.rb +++ b/controls/SV-230341.rb @@ -48,9 +48,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer, if the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe parse_config_file('/etc/security/faillock.conf') do its('silent') { should_not be_nil } diff --git a/controls/SV-230342.rb b/controls/SV-230342.rb index 9910854..6ad2fea 100644 --- a/controls/SV-230342.rb +++ b/controls/SV-230342.rb @@ -1,6 +1,6 @@ control 'SV-230342' do - title 'RHEL 8 must log user name information when unsuccessful logon attempts -occur.' + title "RHEL 8 must log user name information when unsuccessful logon attempts +occur." desc 'By limiting the number of failed logon attempts, the risk of unauthorized system access via user password guessing, otherwise known as brute-force attacks, is reduced. Limits are imposed by locking the account. @@ -75,10 +75,11 @@ tag cci: ['CCI-000044'] tag nist: ['AC-7 a'] - only_if("\n" + <<~MESSAGE, impact: 0.0) do - This check only applies to RHEL versions 8.0 or 8.1. + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this check is Not Applicable. MESSAGE + only_if(message, impact: 0.0) do ['8.0', '8.1'].include?(os.version) end diff --git a/controls/SV-230343.rb b/controls/SV-230343.rb index ff17a28..3b1720f 100644 --- a/controls/SV-230343.rb +++ b/controls/SV-230343.rb @@ -48,9 +48,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer, if the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe parse_config_file('/etc/security/faillock.conf') do its('audit') { should_not be_nil } diff --git a/controls/SV-230344.rb b/controls/SV-230344.rb index 829224f..11e7ebd 100644 --- a/controls/SV-230344.rb +++ b/controls/SV-230344.rb @@ -79,10 +79,11 @@ tag 'host' tag 'container' - only_if("\n" + <<~MESSAGE, impact: 0.0) do - This check only applies to RHEL versions 8.0 or 8.1. + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this check is Not Applicable. MESSAGE + only_if(message, impact: 0.0) do ['8.0', '8.1'].include?(os.version) end diff --git a/controls/SV-230345.rb b/controls/SV-230345.rb index c6e2d61..2da5b48 100644 --- a/controls/SV-230345.rb +++ b/controls/SV-230345.rb @@ -49,9 +49,13 @@ tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer, if the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe parse_config_file('/etc/security/faillock.conf') do its('even_deny_root') { should_not be_nil } diff --git a/controls/SV-230475.rb b/controls/SV-230475.rb index 0351d62..2e2b1d9 100644 --- a/controls/SV-230475.rb +++ b/controls/SV-230475.rb @@ -62,13 +62,13 @@ !virtualization.system.eql?('docker') } - audit_tools = %w(/usr/sbin/auditctl + audit_tools = %w[/usr/sbin/auditctl /usr/sbin/auditd /usr/sbin/ausearch /usr/sbin/aureport /usr/sbin/autrace /usr/sbin/rsyslogd - /usr/sbin/augenrules) + /usr/sbin/augenrules] if package('aide').installed? audit_tools.each do |tool| diff --git a/controls/SV-244533.rb b/controls/SV-244533.rb index 1a7e655..22d31b3 100644 --- a/controls/SV-244533.rb +++ b/controls/SV-244533.rb @@ -57,9 +57,13 @@ module in the /etc/pam.d/system-auth file. tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer, if the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-244534.rb b/controls/SV-244534.rb index 5bf524e..b3f6157 100644 --- a/controls/SV-244534.rb +++ b/controls/SV-244534.rb @@ -58,9 +58,13 @@ module in the /etc/pam.d/password-auth file. tag 'host' tag 'container' - only_if('This check applies to RHEL versions 8.2 or newer, if the system is RHEL version 8.0 or 8.1, this check is not applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end describe pam('/etc/pam.d/password-auth') do its('lines') { should match_pam_rule('auth required pam_faillock.so preauth') } diff --git a/controls/SV-250315.rb b/controls/SV-250315.rb index 9ec6040..e4f3e94 100644 --- a/controls/SV-250315.rb +++ b/controls/SV-250315.rb @@ -69,9 +69,13 @@ module with the following command: tag nist: ['AC-7 a', 'AC-7 b'] tag 'host' - only_if('This check applies to RHEL version 8.2 and later. If the system is not RHEL version 8.2 or newer, this check is Not Applicable.', impact: 0.0) { - (os.release.to_f) >= 8.2 - } + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE + only_if(message, impact: 0.0) do + ['8.0', '8.1'].include?(os.version) + end if virtualization.system.eql?('docker') impact 0.0 diff --git a/controls/SV-250316.rb b/controls/SV-250316.rb index 47249cd..4e4a9b4 100644 --- a/controls/SV-250316.rb +++ b/controls/SV-250316.rb @@ -65,10 +65,11 @@ module with the following command: tag 'host' tag 'container' - only_if("\n" + <<~MESSAGE, impact: 0.0) do - This check only applies to RHEL versions 8.0 or 8.1. + message = <<~MESSAGE + \nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this check is Not Applicable. MESSAGE + only_if(message, impact: 0.0) do ['8.0', '8.1'].include?(os.version) end From 488d9d33459c2ef756fe0252d6df674d1e612f99 Mon Sep 17 00:00:00 2001 From: Aaron Lippold Date: Thu, 6 Feb 2025 00:44:34 -0500 Subject: [PATCH 11/17] updated controls to use the os.version.minor for clarity Signed-off-by: Aaron Lippold --- controls/SV-230333.rb | 4 ++-- controls/SV-230334.rb | 4 ++-- controls/SV-230335.rb | 4 ++-- controls/SV-230336.rb | 4 ++-- controls/SV-230337.rb | 4 ++-- controls/SV-230338.rb | 4 ++-- controls/SV-230339.rb | 4 ++-- controls/SV-230340.rb | 4 ++-- controls/SV-230341.rb | 4 ++-- controls/SV-230343.rb | 4 ++-- controls/SV-230345.rb | 4 ++-- controls/SV-244533.rb | 4 ++-- controls/SV-244534.rb | 4 ++-- controls/SV-250315.rb | 4 ++-- 14 files changed, 28 insertions(+), 28 deletions(-) diff --git a/controls/SV-230333.rb b/controls/SV-230333.rb index 358d6fb..48ee34f 100644 --- a/controls/SV-230333.rb +++ b/controls/SV-230333.rb @@ -49,11 +49,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe parse_config_file('/etc/security/faillock.conf') do diff --git a/controls/SV-230334.rb b/controls/SV-230334.rb index f9de470..516adcb 100644 --- a/controls/SV-230334.rb +++ b/controls/SV-230334.rb @@ -75,11 +75,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230335.rb b/controls/SV-230335.rb index 4ad99c9..74482b9 100644 --- a/controls/SV-230335.rb +++ b/controls/SV-230335.rb @@ -49,11 +49,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe parse_config_file(input('security_faillock_conf')) do diff --git a/controls/SV-230336.rb b/controls/SV-230336.rb index 56494ab..44d791c 100644 --- a/controls/SV-230336.rb +++ b/controls/SV-230336.rb @@ -77,11 +77,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230337.rb b/controls/SV-230337.rb index 0847904..7a14693 100644 --- a/controls/SV-230337.rb +++ b/controls/SV-230337.rb @@ -51,11 +51,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe parse_config_file('/etc/security/faillock.conf') do diff --git a/controls/SV-230338.rb b/controls/SV-230338.rb index 45f237e..5f98561 100644 --- a/controls/SV-230338.rb +++ b/controls/SV-230338.rb @@ -77,11 +77,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230339.rb b/controls/SV-230339.rb index 6d23dd3..2fded8c 100644 --- a/controls/SV-230339.rb +++ b/controls/SV-230339.rb @@ -48,11 +48,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe parse_config_file('/etc/security/faillock.conf') do diff --git a/controls/SV-230340.rb b/controls/SV-230340.rb index c8fda14..1ad8c35 100644 --- a/controls/SV-230340.rb +++ b/controls/SV-230340.rb @@ -73,11 +73,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-230341.rb b/controls/SV-230341.rb index 99a06af..0767b85 100644 --- a/controls/SV-230341.rb +++ b/controls/SV-230341.rb @@ -49,11 +49,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe parse_config_file('/etc/security/faillock.conf') do diff --git a/controls/SV-230343.rb b/controls/SV-230343.rb index 3b1720f..61b5719 100644 --- a/controls/SV-230343.rb +++ b/controls/SV-230343.rb @@ -49,11 +49,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe parse_config_file('/etc/security/faillock.conf') do diff --git a/controls/SV-230345.rb b/controls/SV-230345.rb index 2da5b48..3e2890a 100644 --- a/controls/SV-230345.rb +++ b/controls/SV-230345.rb @@ -50,11 +50,11 @@ tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe parse_config_file('/etc/security/faillock.conf') do diff --git a/controls/SV-244533.rb b/controls/SV-244533.rb index 22d31b3..0c5636e 100644 --- a/controls/SV-244533.rb +++ b/controls/SV-244533.rb @@ -58,11 +58,11 @@ module in the /etc/pam.d/system-auth file. tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end pam_auth_files = input('pam_auth_files') diff --git a/controls/SV-244534.rb b/controls/SV-244534.rb index b3f6157..fd4db4c 100644 --- a/controls/SV-244534.rb +++ b/controls/SV-244534.rb @@ -59,11 +59,11 @@ module in the /etc/pam.d/password-auth file. tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe pam('/etc/pam.d/password-auth') do diff --git a/controls/SV-250315.rb b/controls/SV-250315.rb index e4f3e94..6452b8d 100644 --- a/controls/SV-250315.rb +++ b/controls/SV-250315.rb @@ -70,11 +70,11 @@ module with the following command: tag 'host' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end if virtualization.system.eql?('docker') From 9ca839d1aa575941b2223fe34c7e2d08dbaae90c Mon Sep 17 00:00:00 2001 From: Aaron Lippold Date: Thu, 6 Feb 2025 00:46:43 -0500 Subject: [PATCH 12/17] adding missed control - SV-250316 Signed-off-by: Aaron Lippold --- controls/SV-250316.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/controls/SV-250316.rb b/controls/SV-250316.rb index 4e4a9b4..713c683 100644 --- a/controls/SV-250316.rb +++ b/controls/SV-250316.rb @@ -66,11 +66,11 @@ module with the following command: tag 'container' message = <<~MESSAGE - \nThis check only applies to RHEL versions 8.0 or 8.1.\n - The system is running RHEL version: #{os.version}, this check is Not Applicable. + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE only_if(message, impact: 0.0) do - ['8.0', '8.1'].include?(os.version) + os.version.minor.between?(0, 1) end describe selinux do From f969de560e85d501d764e287df1fd21a3a804370 Mon Sep 17 00:00:00 2001 From: Jon Metzger Date: Thu, 6 Feb 2025 16:30:57 -0500 Subject: [PATCH 13/17] added active_support lib for os resource --- libraries/os.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/os.rb b/libraries/os.rb index 3fec52f..3abeb7a 100644 --- a/libraries/os.rb +++ b/libraries/os.rb @@ -1,4 +1,5 @@ require "inspec/resources/platform" +require 'active_support/core_ext/object/blank' require "rubygems" unless defined?(Gem) # This provides Gem::Version # module Inspec From f3120c109755534aee0cfc9887cb36b0e44f9490 Mon Sep 17 00:00:00 2001 From: Jon Metzger Date: Thu, 6 Feb 2025 16:42:13 -0500 Subject: [PATCH 14/17] 8.1/8.2 message update --- controls/SV-230332.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/controls/SV-230332.rb b/controls/SV-230332.rb index 23f811b..e6d0cae 100644 --- a/controls/SV-230332.rb +++ b/controls/SV-230332.rb @@ -87,10 +87,14 @@ !input('central_account_management') } + message = <<~MESSAGE + \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE if os.version >= '8.2' impact 0.0 describe 'This requirement only applies to RHEL 8 version(s) 8.0 and 8.1' do - skip "Currently on release #{os.version}, this control is Not Applicable." + skip message end else [ From fe64d48a3ccd15059bc613f98c74af9d926145cb Mon Sep 17 00:00:00 2001 From: Jon Metzger Date: Thu, 6 Feb 2025 16:44:58 -0500 Subject: [PATCH 15/17] 8.4 message --- controls/SV-230285.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/controls/SV-230285.rb b/controls/SV-230285.rb index b413bdf..68cdbf8 100644 --- a/controls/SV-230285.rb +++ b/controls/SV-230285.rb @@ -38,10 +38,14 @@ !virtualization.system.eql?('docker') } + message = <<~MESSAGE + \n\nFor RHEL versions 8.4 and above running with kernel FIPS mode enabled as specified by RHEL-08-010020\n + The system is running RHEL version: #{os.version}, this requirement is Not Applicable. + MESSAGE if os.release.to_f >= 8.4 && input('use_fips') == true impact 0.0 describe 'For RHEL versions 8.4 and above running with kernel FIPS mode enabled as specified by RHEL-08-010020, this requirement is Not Applicable.' do - skip "Currently on release #{os.release}, this control is Not Applicable." + skip message end else describe service('rngd') do From 37a6ed4e41208fd26f36b7199914b8381cc3abad Mon Sep 17 00:00:00 2001 From: Aaron Lippold Date: Thu, 6 Feb 2025 22:54:11 -0500 Subject: [PATCH 16/17] fixed controls to use os.release in favor of os.version, extra support in OS should not be needed, likey a local issue Signed-off-by: Aaron Lippold --- libraries/os.rb | 4 +- libraries/random_number_generator.rb | 562 +++++++++++++++++++++++++++ 2 files changed, 565 insertions(+), 1 deletion(-) create mode 100644 libraries/random_number_generator.rb diff --git a/libraries/os.rb b/libraries/os.rb index 3abeb7a..e46219b 100644 --- a/libraries/os.rb +++ b/libraries/os.rb @@ -1,5 +1,7 @@ require "inspec/resources/platform" -require 'active_support/core_ext/object/blank' +require "active_support/core_ext/object/blank" +## ^^^ THIS SHOULD NOT BE NEEDED ^^^ ## +# What version of inspec are you running? require "rubygems" unless defined?(Gem) # This provides Gem::Version # module Inspec diff --git a/libraries/random_number_generator.rb b/libraries/random_number_generator.rb new file mode 100644 index 0000000..4d34cff --- /dev/null +++ b/libraries/random_number_generator.rb @@ -0,0 +1,562 @@ +# TODO: Add when we have a Windows RNG implementation +# require "inspec/resources/powershell" +require "hashie/mash" + +module Inspec::Resources + # rubocop:disable Metrics/MethodLength + + module RNGManagementSelector + def select_rng_manager(os) + Inspec::Log.debug "Selecting RNG manager for OS: #{os[:family]}" + if os.linux? + LinuxRNG.new(inspec) + elsif os.windows? + WindowsRNG.new(inspec) + elsif os[:family] == "darwin" + MacOSRNG.new(inspec) + elsif os[:family] == "freebsd" + FreeBSDRNG.new(inspec) + else + GenericUnixRNG.new(inspec) + end + end + end + + class RandomNumberGenerator < Inspec.resource(1) + include RNGManagementSelector + + name "random_number_generator" + supports platform: "unix" + # TODO: Add support for Windows RNG through testing + # The Windows RNG implementation is untested and may not work as expected. + # supports platform: 'windows' + + desc "Tests the presence and status of a random number generator." + example <<~EXAMPLE + # General usage + describe random_number_generator do + it { should exist } + it { should be_available } + it { should have_entropy } + it { should have_sources } + it { should have_services } + it { should be_running } + its('type') { should match(/hardware|csprng|software/) } + its('sources') { should include '/dev/random' } + end + + # Platform-specific tests + describe random_number_generator do + # Linux/FreeBSD hardware tests + it { should be_hardware } if ['linux', 'freebsd'].include?(os[:family]) + + # macOS CSPRNG tests + if os[:family] == 'darwin' + it { should be_csprng } + its('sources') { should include '/dev/random' } + its(%w[csprng_status system]) { should match(/^macOS/) } + its(%w[csprng_status architecture]) { should match(/(Apple Silicon|Intel)/) } + its(%w[csprng_status random_subsystem]) { should_not be_empty } + # Intel-specific tests + if its(%w[csprng_status architecture]) == 'Intel' + its('sources') { should include 'RDRAND' } + end + end + end + + # Windows tests (future implementation) + if os.windows? + describe random_number_generator do + it { should exist } + it { should be_available } + it { should be_running } + its('services') { should include 'CryptoSvc' } + its('sources') { should include 'CryptoAPI' } + # Hardware RNG checks + its('sources') { should match /'TPM|RDRAND'/ } + end + end + EXAMPLE + + attr_reader :rng_info + + # provide as this is a standard in inspec resources generally + alias params rng_info + + def initialize + super() + Inspec::Log.debug "Initializing RandomNumberGenerator resource" + @rng_provider = select_rng_manager(inspec.os) + skip_resource "The `random_number_generator` resource is not supported on your OS yet." if @rng_provider.nil? + + @cached_results = {} # Initialize the cache hash + @rng_info = Hashie::Mash.new(@rng_provider.rng_info) + Inspec::Log.debug "RNG info: #{@rng_info}" + end + + # Core property readers - using method_missing for dynamic property access + def method_missing(method_name, *args) + return super unless respond_to_missing?(method_name) + + @cached_results[method_name] ||= begin + property_name = method_name.to_s.gsub(/\?$/, "") + Inspec::Log.debug "Accessing property: #{property_name}" + @rng_info[property_name.to_sym] + end + end + + def respond_to_missing?(method_name, include_private = false) + property_name = method_name.to_s.gsub(/\?$/, "") + @rng_info.key?(property_name.to_sym) || super + end + + # Primary state checks + def exist? + Inspec::Log.debug "Checking if RNG exists" + @rng_info.exist + end + + def available? + Inspec::Log.debug "Checking if RNG is available" + @rng_info.available + end + + # Type checks + def hardware? + Inspec::Log.debug "Checking if RNG type is hardware" + type == "hardware" + end + + def software? + Inspec::Log.debug "Checking if RNG type is software" + type == "software" + end + + def csprng? + Inspec::Log.debug "Checking if RNG type is CSPRNG" + type == "csprng" + end + + # Resource state checks + def has_entropy? + Inspec::Log.debug "Checking if entropy is available" + !entropy.nil? && entropy > 0 + end + + def has_sources? + Inspec::Log.debug "Checking if RNG has sources" + sources&.any? + end + + def has_services? + Inspec::Log.debug "Checking if RNG has services" + services&.any? + end + + def running? + Inspec::Log.debug "Checking if RNG service is running" + !!running + end + + def value(key) + return @rng_info unless key + + # Handle array access for nested properties + if key.is_a?(Array) + current = @rng_info + key.each { |k| current = current[k] if current } + current + else + @rng_info[key] + end + end + + def [](name, *rest) + return value(name) if rest.empty? + + # Handle array-style access for nested properties + current = params + Array([name, *rest]).each do |key| + return nil unless current.respond_to?(:[]) + + current = current[key] + return nil if current.nil? # Return nil early if any part of the path is nil + end + current + end + + def to_s + "Random Number Generator (#{type})" + end + + private + + def collect_rng_details + Inspec::Log.debug "Collecting RNG details" + @rng_info + end + end # class RandomNumberGenerator + + # RNGInfo is a base class for platform-specific RNG implementations. + # It provides caching helpers for file lookups and a helper to construct + # the standardized RNG info hash. + class RNGInfo + attr_reader :inspec + + def initialize(inspec) + @inspec = inspec + @rng_info = nil + end + + # Add caching helpers for file lookups + def file_cache + @file_cache ||= {} + end + + def cached_file(path) + file_cache[path] ||= inspec.file(path) + end + + def rng_info + @rng_info ||= begin + base_info = default_info.merge(collect_platform_info) + Hashie::Mash.new(base_info) + end + end + + protected + + def default_info + { + exist: false, + available: false, + type: "unknown", + sources: [], + active: nil, + entropy: nil, + running: nil, + services: [], + } + end + + # Platform implementations can extend with their specific properties + def collect_platform_info + {} + end + end + + # --- Linux Implementation --- + class LinuxRNG < RNGInfo + def initialize(inspec) + super(inspec) + Inspec::Log.debug "Initializing LinuxRNG" + end + + protected + + def collect_platform_info + # Combine file existence checks into a single command + file_checks = { + hw: "/dev/hwrng", # Was hw_random + intel: "/dev/intel-rng", # Was intel_rng + tpm: "/dev/tpm0", # Was tpm_rng + } + file_check_cmd = file_checks.map do |key, file| + "test -e #{file} && echo #{key}=true || echo #{key}=false" + end.join(" && ") + file_check_output = inspec.command(file_check_cmd).stdout.split("\n").map { |line| line.split("=") }.to_h + hw = file_check_output["hw"] == "true" + intel = file_check_output["intel"] == "true" + tpm = file_check_output["tpm"] == "true" + + # Combine system file reads into a single command + system_files = { + active: "/sys/devices/virtual/misc/hw_random/rng_current", # Was active_rng + available: "/sys/devices/virtual/misc/hw_random/rng_available", # Was rng_available + entropy: "/proc/sys/kernel/random/entropy_avail", # Was entropy_available + } + system_file_cmd = system_files.map { |key, file| "echo #{key}=$(cat #{file} || echo -n)" }.join(" && ") + system_file_output = inspec.command(system_file_cmd).stdout.split("\n").map { |line| line.split("=", 2) }.to_h + active = system_file_output["active"] + available = system_file_output["available"].split + entropy = system_file_output["entropy"].to_i + + # Check services in parallel + services = %w{rngd haveged jitterentropy} + service_cmds = services.map do |service| + "systemctl show --no-pager --all #{service} && systemctl is-active #{service} --quiet && systemctl is-enabled #{service} --quiet" + end + service_cmd = service_cmds.join(" & ") + service_output = inspec.command(service_cmd).stdout.split("\n") + rngd_running = service_output.any? { |line| line.include?("rngd") && line.include?("active") } + haveged_running = service_output.any? { |line| line.include?("haveged") && line.include?("active") } + jitterentropy_running = service_output.any? { |line| line.include?("jitterentropy") && line.include?("active") } + + sources = ["/dev/random", "/dev/urandom"] + sources << "/dev/hwrng" if hw + sources << "/dev/intel-rng" if intel + sources << "/dev/tpm0" if tpm + + type = if hw || intel || tpm || !available.empty? + "hardware" + else + "software" + end + + services = [] + services << "rngd" if rngd_running + services << "haveged" if haveged_running + services << "jitterentropy" if jitterentropy_running + + { + exist: !sources.empty?, + available: !entropy.nil? && entropy > 0, + type: type, + sources: sources, + active: active, + entropy: entropy, + running: rngd_running || haveged_running || jitterentropy_running, + services: services, + } + end + end + + # --- FreeBSD Implementation --- + class FreeBSDRNG < RNGInfo + def initialize(inspec) + super(inspec) + Inspec::Log.debug "Initializing FreeBSDRNG" + end + + protected + + def collect_platform_info + # Combine checks into a single command + cmd = <<~CMD + kldstat | grep random && echo yarrow_loaded=true || echo yarrow_loaded=false + dmesg | grep -i rdrand && echo rdrand_available=true || echo rdrand_available=false + test -e /dev/intel-rng && echo intel_rng=true || echo intel_rng=false + CMD + output = inspec.command(cmd).stdout.split("\n").map { |line| line.split("=") }.to_h + yarrow_loaded = output["yarrow_loaded"] == "true" + rdrand_available = output["rdrand_available"] == "true" + intel_rng = output["intel_rng"] == "true" + + sources = [] + sources << "/dev/random" if cached_file("/dev/random").exist? + sources << "/dev/urandom" if cached_file("/dev/urandom").exist? + sources << "RDRAND" if rdrand_available + sources << "intel-rng" if intel_rng + + type = if rdrand_available || intel_rng + "hardware" + elsif yarrow_loaded + "software" + else + "unknown" + end + + { + exist: !sources.empty?, + available: !sources.empty?, + type: type, + sources: sources, + active: yarrow_loaded ? "Yarrow" : nil, + running: yarrow_loaded, + } + end + end + + # --- macOS Implementation --- + class MacOSRNG < RNGInfo + def initialize(inspec) + super(inspec) + Inspec::Log.debug "Initializing MacOSRNG" + end + + protected + + def collect_platform_info + # Get system information first + os_info = inspec.command("sw_vers -productVersion").stdout.strip + uname = inspec.command("uname -a").stdout.strip + arch = uname.include?("ARM64") ? "Apple Silicon" : "Intel" + kernel_version = begin + uname.match(/Kernel Version ([^;]+)/)[1].strip + rescue StandardError + "unknown" + end + + # Check random device + random_exist = inspec.file("/dev/random").exist? + rdrand_available = arch == "Intel" && inspec.command("sysctl -n hw.optional.rdrand").stdout.include?("1") + + # Try to get random subsystem info, but don't rely on it + random_info = inspec.command("sysctl kern.random").stdout + random_subsystem = random_info.empty? ? "Not exposed via sysctl" : random_info.strip + + # Build sources array + sources = [] + sources << "/dev/random" if random_exist + sources << "RDRAND" if rdrand_available + + # Don't convert to JSON string, keep as hash + { + exist: random_exist, + available: random_exist, + type: "csprng", + sources: sources, # Now sources is properly defined + active: random_exist ? "/dev/random" : nil, + running: true, + csprng_status: { + system: "macOS #{os_info}", + architecture: arch, + kernel: kernel_version, + random_subsystem: random_subsystem, + }, + } + end + end + + # --- Windows Implementation --- + # TODO: Add support for Windows RNG through testing + class WindowsRNG < RNGInfo + def initialize(inspec) + super(inspec) + Inspec::Log.debug "Initializing WindowsRNG" + end + + protected + + def collect_platform_info + script = <<~EOH + $rng = @{ + CryptoAPI = $false + TPM = $false + RDRAND = $false + } + + # Check CryptoAPI + try { + $null = [System.Security.Cryptography.RNGCryptoServiceProvider]::new() + $rng.CryptoAPI = $true + } catch {} + + # Check TPM + try { + $tpm = Get-Tpm + $rng.TPM = ($tpm.TpmPresent -and $tpm.TpmReady) + } catch {} + + # Check RDRAND (Intel CPU RNG) + $cpu = Get-WmiObject Win32_Processor + $rng.RDRAND = $cpu.Manufacturer -match "Intel" -and $cpu.Caption -match "Intel" + + ConvertTo-Json $rng + EOH + + result = inspec.powershell(script) + return default_info unless result.exit_status == 0 + + begin + rng_data = JSON.parse(result.stdout) + sources = [] + sources << "CryptoAPI" if rng_data["CryptoAPI"] + sources << "TPM" if rng_data["TPM"] + sources << "RDRAND" if rng_data["RDRAND"] + + active = if rng_data["TPM"] + "TPM" + elsif rng_data["RDRAND"] + "RDRAND" + elsif rng_data["CryptoAPI"] + "CryptoAPI" + end + + type = if rng_data["TPM"] || rng_data["RDRAND"] + "hardware" + elsif rng_data["CryptoAPI"] + "csprng" + else + "unknown" + end + + cng_properties = inspec.powershell("Get-CNGProperty -ProviderName Microsoft Primitive Provider").stdout + + { + exist: !sources.empty?, + available: !sources.empty?, + type: type, + sources: sources, + active: active, + running: true, + services: ["CryptoSvc"], + cng_properties: cng_properties, + } + rescue StandardError + default_info + end + end + + private + + def default_info + Inspec::Log.debug "Returning default RNG info for Windows" + { + exist: false, + available: false, + type: "unknown", + sources: [], + active: nil, + entropy: nil, + running: nil, + services: [], + csprng_status: nil, + cng_properties: nil, + } + end + + protected + + def platform_info + { + cng_properties: collect_cng_properties, + } + end + end + + # --- Generic Unix Fallback --- + class GenericUnixRNG < RNGInfo + def initialize(inspec) + super(inspec) + Inspec::Log.debug "Initializing GenericUnixRNG" + end + + protected + + def collect_platform_info + # Combine checks into a single command + cmd = <<~CMD + test -e /dev/random && echo random_exist=true || echo random_exist=false + dmesg | grep -i rng + CMD + output = inspec.command(cmd).stdout.split("\n") + random_exist = output[0].include?("random_exist=true") + dmesg_output = output[1..-1].join("\n") + + sources = random_exist ? ["/dev/random"] : [] + active = random_exist ? "/dev/random" : nil # Was active_rng + type = dmesg_output.empty? ? "unknown" : "hardware" + + { + exist: random_exist, + available: random_exist, + type: type, + sources: sources, + active: active, + running: nil, + dmesg_output: dmesg_output, + } + end + end +end From dbe0da598c6cf9da38d28c4bf54fa18d8bb14e49 Mon Sep 17 00:00:00 2001 From: Aaron Lippold Date: Thu, 6 Feb 2025 22:54:11 -0500 Subject: [PATCH 17/17] fixed controls to use os.release in favor of os.version, extra support in OS should not be needed, likey a local issue Signed-off-by: Aaron Lippold --- controls/SV-230285.rb | 2 +- controls/SV-230332.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controls/SV-230285.rb b/controls/SV-230285.rb index 68cdbf8..878c222 100644 --- a/controls/SV-230285.rb +++ b/controls/SV-230285.rb @@ -42,7 +42,7 @@ \n\nFor RHEL versions 8.4 and above running with kernel FIPS mode enabled as specified by RHEL-08-010020\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE - if os.release.to_f >= 8.4 && input('use_fips') == true + if os.version.minor >= 4 && input('use_fips') == true impact 0.0 describe 'For RHEL versions 8.4 and above running with kernel FIPS mode enabled as specified by RHEL-08-010020, this requirement is Not Applicable.' do skip message diff --git a/controls/SV-230332.rb b/controls/SV-230332.rb index e6d0cae..e61968d 100644 --- a/controls/SV-230332.rb +++ b/controls/SV-230332.rb @@ -91,7 +91,7 @@ \n\nThis check only applies to RHEL versions 8.0 or 8.1.\n The system is running RHEL version: #{os.version}, this requirement is Not Applicable. MESSAGE - if os.version >= '8.2' + if os.version.minor >= '2' impact 0.0 describe 'This requirement only applies to RHEL 8 version(s) 8.0 and 8.1' do skip message