inspec-core 5.22.72 → 5.22.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1561e49537c4bd8b615a78d099d922a0915c71429fcdfb4ca6197105712ca3aa
4
- data.tar.gz: d756477c4172ff54a6a69f6905c0f0034b484f9ca38b45fda8a7d6efa7c5f748
3
+ metadata.gz: 6b46f57de93a21fa00ddeb70944cc1bb3cf846c73d1b33c5460496472773b0fa
4
+ data.tar.gz: a1f020b14dc5f06c81f98d7fabaa593b5a0696b5cd4370625382b627c216493e
5
5
  SHA512:
6
- metadata.gz: 93849cdca52ac4bc4bec15aebd4933e623229f4c10378fb2d85316c6496d45cc9ebe7ed2e1c1aa4f1a296779237cb06b204f5d61af8f7d1a7b2642c9a9e4720a
7
- data.tar.gz: 54988d5e27e76412c03eca453f7887414a536ee16607fbf2c1ecd7e502136f555700bba9c88e59967ab6857fa198c4138b517090183f31b72e88f54a46926669
6
+ metadata.gz: f72371f72e1195698128502801aefea2e698bd2c705c00b849547c2f8b18881bb05964de87715cbea5301ee6284db60fba6a9f080915d3f672686174c0ec1e59
7
+ data.tar.gz: 56a96407e6c3dd29f7d33c0ee128cf419aac43e01c48c6c220c3041cf20aeee4478d9be1ec280f2732391ca9d7eef5db19371e69d6105036e13fbbca5a6c3e53
data/Gemfile CHANGED
@@ -39,7 +39,8 @@ group :test do
39
39
  gem "mocha"
40
40
  # Pinning this version as it breaking for ruby 3.1.0
41
41
  gem "nokogiri", "< 1.17.2"
42
- gem "pry-byebug"
42
+ # Pinning this version as it breaking for ruby 3.0.0
43
+ gem "pry-byebug", "< 3.11.0"
43
44
  gem "pry"
44
45
  gem "rake"
45
46
  gem "simplecov"
data/inspec-core.gemspec CHANGED
@@ -55,5 +55,5 @@ Gem::Specification.new do |spec|
55
55
  # which was causing a LoadError ('cannot load such file -- ast') for users/applications using 'inspec-core'.
56
56
  spec.add_dependency "cookstyle"
57
57
 
58
- spec.add_dependency "train-core", "~> 3.10"
58
+ spec.add_dependency "train-core", "~> 3.12.13"
59
59
  end
@@ -12,5 +12,6 @@ module Inspec
12
12
  class ProfileSigningKeyNotFound < ArgumentError; end
13
13
  class WaiversFileNotReadable < ArgumentError; end
14
14
  class WaiversFileDoesNotExist < ArgumentError; end
15
+ class WaiversFileInvalidFormatting < ArgumentError; end
15
16
  end
16
17
  end
@@ -575,7 +575,7 @@ module Inspec
575
575
  include_tests: include_tests)
576
576
 
577
577
  # Collect all metadata defined in the control block and inputs defined inside the control block
578
- src.ast.each_node { |n|
578
+ src.ast&.each_node { |n|
579
579
  ctl_id_collector.process(n)
580
580
  input_collector.process(n)
581
581
  }
@@ -637,7 +637,7 @@ module Inspec
637
637
  }
638
638
  source_location_ref = @source_reader.target.abs_path(control_filename)
639
639
  Inspec::Profile::AstHelper::TitleCollector.new(group_data)
640
- .process(src.ast.child_nodes.first) # Picking the title defined for the whole controls file
640
+ .process(src.ast&.child_nodes&.first) # Picking the title defined for the whole controls file
641
641
  group_controls = @info_from_parse[:controls].select { |control| control[:source_location][:ref] == source_location_ref }
642
642
  group_data[:controls] = group_controls.map { |control| control[:id] }
643
643
 
@@ -39,11 +39,17 @@ module Inspec::Resources
39
39
  # expected result:
40
40
  # Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting
41
41
  # WIN-MB8NINQ388J,System,Kerberos Authentication Service,{0CCE9242-69AE-11D9-BED3-505054503030},No Auditing,
42
- result ||= inspec.command("Auditpol /get /subcategory:'#{key}' /r").stdout
42
+ auditpol_cmd = "Auditpol /get /subcategory:'#{key}' /r"
43
+ result ||= inspec.command(auditpol_cmd)
44
+
45
+ unless result.exit_status == 0
46
+ error = result.stdout + "\n" + result.stderr
47
+ raise Inspec::Exceptions::ResourceFailed, "Error while executing #{auditpol_cmd} command: #{error}"
48
+ end
43
49
 
44
50
  # find line
45
51
  target = nil
46
- result.each_line do |s|
52
+ result.stdout.each_line do |s|
47
53
  target = s.strip if s =~ /\b.*#{key}.*\b/
48
54
  end
49
55
 
@@ -24,12 +24,18 @@ module Secrets
24
24
  @inputs = ::YAML.load_file(target)
25
25
  end
26
26
 
27
- if @inputs == false || !@inputs.is_a?(Hash)
28
- Inspec::Log.warn("#{self.class} unable to parse #{target}: invalid YAML or contents is not a Hash")
27
+ # In case of empty yaml file raise the warning else raise the parsing error.
28
+ if !@inputs || @inputs.empty?
29
+ Inspec::Log.warn("Unable to parse #{target}: YAML file is empty.")
29
30
  @inputs = nil
31
+ elsif !@inputs.is_a?(Hash)
32
+ # Exits with usage error.
33
+ Inspec::Log.error("Unable to parse #{target}: invalid YAML or contents is not a Hash")
34
+ Inspec::UI.new.exit(:usage_error)
30
35
  end
31
36
  rescue => e
32
- raise "Error reading InSpec inputs: #{e}"
37
+ # Any other error related to Yaml parsing will be raised here.
38
+ raise "Error reading YAML file #{target}: #{e}"
33
39
  end
34
40
  end
35
41
  end
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "5.22.72".freeze
2
+ VERSION = "5.22.80".freeze
3
3
  end
@@ -5,6 +5,8 @@ require "inspec/utils/waivers/json_file_reader"
5
5
  module Inspec
6
6
  class WaiverFileReader
7
7
 
8
+ SUPPORTED_FILE_EXTENSION = %w{.yaml .yml .csv .json}.freeze
9
+
8
10
  def self.fetch_waivers_by_profile(profile_id, files)
9
11
  read_waivers_from_file(profile_id, files) if @waivers_data.nil? || @waivers_data[profile_id].nil?
10
12
  @waivers_data[profile_id]
@@ -15,49 +17,105 @@ module Inspec
15
17
  output = {}
16
18
 
17
19
  files.each do |file_path|
18
- file_extension = File.extname(file_path)
19
- data = nil
20
- if [".yaml", ".yml"].include? file_extension
21
- data = Secrets::YAML.resolve(file_path)
22
- unless data.nil?
23
- data = data.inputs
24
- validate_json_yaml(data)
25
- end
26
- elsif file_extension == ".csv"
27
- data = Waivers::CSVFileReader.resolve(file_path)
28
- headers = Waivers::CSVFileReader.headers
29
- validate_headers(headers)
30
- elsif file_extension == ".json"
31
- data = Waivers::JSONFileReader.resolve(file_path)
32
- validate_json_yaml(data) unless data.nil?
33
- end
34
- output.merge!(data) if !data.nil? && data.is_a?(Hash)
20
+ next unless valid_waiver_file?(file_path)
35
21
 
36
- if data.nil?
37
- raise Inspec::Exceptions::WaiversFileNotReadable,
38
- "Cannot find parser for waivers file '#{file_path}'. " \
39
- "Check to make sure file has the appropriate extension."
40
- end
22
+ data = parse_waiver_file(file_path)
23
+ output.merge!(data) if data.is_a?(Hash)
24
+ rescue Inspec::Exceptions::WaiversFileNotReadable, Inspec::Exceptions::WaiversFileInvalidFormatting => e
25
+ Inspec::Log.error "Error reading waivers file #{file_path}. #{e.message}"
26
+ Inspec::UI.new.exit(:usage_error)
41
27
  end
42
28
 
43
29
  @waivers_data[profile_id] = output
44
30
  end
45
31
 
46
- def self.validate_headers(headers, json_yaml = false)
47
- required_fields = json_yaml ? %w{justification} : %w{control_id justification}
48
- all_fields = %w{control_id justification expiration_date run}
32
+ def self.valid_waiver_file?(file_path)
33
+ # Check if the file is readable
34
+ file_extension = File.extname(file_path).downcase
35
+ unless SUPPORTED_FILE_EXTENSION.include?(file_extension)
36
+ raise Inspec::Exceptions::WaiversFileNotReadable,
37
+ "Unsupported file extension for '#{file_path}'. Allowed waiver file extensions: #{SUPPORTED_FILE_EXTENSION.join(", ")}"
38
+ end
39
+
40
+ # Check if the file is empty
41
+ if File.zero?(file_path)
42
+ Inspec::Log.warn "Waivers file '#{file_path}' is empty. Skipping waivers."
43
+ return false
44
+ end
49
45
 
50
- Inspec::Log.warn "Missing column headers: #{(required_fields - headers)}" unless (required_fields - headers).empty?
51
- Inspec::Log.warn "Invalid column header: Column can't be nil" if headers.include? nil
52
- Inspec::Log.warn "Extra column headers: #{(headers - all_fields)}" unless (headers - all_fields).empty?
46
+ true
47
+ end
48
+
49
+ def self.parse_waiver_file(file_path)
50
+ file_extension = File.extname(file_path).downcase
51
+
52
+ case file_extension
53
+ when ".yaml", ".yml"
54
+ data = Secrets::YAML.resolve(file_path)&.inputs
55
+ validate_json_yaml(data)
56
+ when ".csv"
57
+ data = Waivers::CSVFileReader.resolve(file_path)
58
+ validate_csv_headers(Waivers::CSVFileReader.headers)
59
+ when ".json"
60
+ data = Waivers::JSONFileReader.resolve(file_path)
61
+ validate_json_yaml(data)
62
+ end
63
+
64
+ data
65
+ end
66
+
67
+ def self.all_fields
68
+ %w{control_id justification expiration_date run}
69
+ end
70
+
71
+ def self.validate_csv_headers(headers)
72
+ invalid_headers_info = fetch_invalid_headers_info(headers)
73
+ # Warn if blank column found in csv file
74
+ Inspec::Log.warn "Invalid column headers: Column can't be nil" if invalid_headers_info[:blank_column]
75
+ # Warn if extra header found in csv file
76
+ Inspec::Log.warn "Extra header/s #{invalid_headers_info[:extra_headers]}" unless invalid_headers_info[:extra_headers].empty?
77
+ unless invalid_headers_info[:missing_required_fields].empty?
78
+ raise Inspec::Exceptions::WaiversFileInvalidFormatting,
79
+ "Missing required header/s #{invalid_headers_info[:missing_required_fields]}. Fix headers in file to proceed."
80
+ end
81
+ end
82
+
83
+ def self.fetch_invalid_headers_info(headers, json_yaml = false)
84
+ required_fields = json_yaml ? %w{justification} : %w{control_id justification}
85
+ data = {}
86
+ data[:missing_required_fields] = []
87
+ # Finds missing required fields
88
+ unless (required_fields - headers).empty?
89
+ data[:missing_required_fields] = required_fields - headers
90
+ end
91
+ # If column with no header found set the blank_column flag. Only applicable for csv
92
+ data[:blank_column] = headers.include?(nil) ? true : false
93
+ # Find extra headers/parameters
94
+ data[:extra_headers] = (headers - all_fields)
95
+ data
53
96
  end
54
97
 
55
98
  def self.validate_json_yaml(data)
56
- headers = []
57
- data.each_value do |value|
58
- headers.push value.keys
99
+ return if data.nil?
100
+
101
+ missing_required_field = false
102
+ data.each do |key, value|
103
+ # In case of yaml or json we need to validate headers/parametes for each value
104
+ invalid_headers_info = fetch_invalid_headers_info(value.keys, true)
105
+ # WARN in case of extra parameters found in each waived control
106
+ Inspec::Log.warn "Control ID #{key}: extra parameter/s #{invalid_headers_info[:extra_headers]}" unless invalid_headers_info[:extra_headers].empty?
107
+ unless invalid_headers_info[:missing_required_fields].empty?
108
+ missing_required_field = true
109
+ # Log error for each waived control
110
+ Inspec::Log.error "Control ID #{key}: missing required parameter/s #{invalid_headers_info[:missing_required_fields]}"
111
+ end
112
+ end
113
+
114
+ # Raise error if any of the waived control has missing required filed
115
+ if missing_required_field
116
+ raise Inspec::Exceptions::WaiversFileInvalidFormatting,
117
+ "Missing required parameter [justification]. Fix parameters in file to proceed."
59
118
  end
60
- validate_headers(headers.flatten.uniq, true)
61
119
  end
62
120
  end
63
121
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.22.72
4
+ version: 5.22.80
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef InSpec Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-03 00:00:00.000000000 Z
11
+ date: 2025-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -390,14 +390,14 @@ dependencies:
390
390
  requirements:
391
391
  - - "~>"
392
392
  - !ruby/object:Gem::Version
393
- version: '3.10'
393
+ version: 3.12.13
394
394
  type: :runtime
395
395
  prerelease: false
396
396
  version_requirements: !ruby/object:Gem::Requirement
397
397
  requirements:
398
398
  - - "~>"
399
399
  - !ruby/object:Gem::Version
400
- version: '3.10'
400
+ version: 3.12.13
401
401
  description: InSpec provides a framework for creating end-to-end infrastructure tests.
402
402
  You can use it for integration or even compliance testing. Create fully portable
403
403
  test profiles and use them in your workflow to ensure stability and security. Integrate
@@ -874,7 +874,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
874
874
  - !ruby/object:Gem::Version
875
875
  version: '0'
876
876
  requirements: []
877
- rubygems_version: 3.2.3
877
+ rubygems_version: 3.3.27
878
878
  signing_key:
879
879
  specification_version: 4
880
880
  summary: Infrastructure and compliance testing. Core library.