inspec 1.51.0 → 1.51.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -15
  3. data/README.md +1 -1
  4. data/docs/glossary.md +99 -0
  5. data/docs/resources/aide_conf.md.erb +16 -9
  6. data/docs/resources/apache.md.erb +66 -0
  7. data/docs/resources/apache_conf.md.erb +11 -5
  8. data/docs/resources/apt.md.erb +1 -1
  9. data/docs/resources/audit_policy.md.erb +1 -1
  10. data/docs/resources/auditd_conf.md.erb +12 -9
  11. data/docs/resources/bash.md.erb +24 -12
  12. data/docs/resources/bond.md.erb +26 -24
  13. data/docs/resources/bridge.md.erb +18 -11
  14. data/docs/resources/bsd_service.md.erb +11 -2
  15. data/docs/resources/command.md.erb +30 -29
  16. data/docs/resources/cpan.md.erb +33 -17
  17. data/docs/resources/cran.md.erb +26 -17
  18. data/docs/resources/crontab.md.erb +18 -1
  19. data/docs/resources/csv.md.erb +13 -7
  20. data/docs/resources/{dh_params.md → dh_params.md.erb} +30 -6
  21. data/docs/resources/directory.md.erb +9 -4
  22. data/docs/resources/docker.md.erb +1 -1
  23. data/docs/resources/docker_container.md.erb +32 -26
  24. data/docs/resources/docker_image.md.erb +29 -26
  25. data/docs/resources/docker_service.md.erb +37 -31
  26. data/docs/resources/elasticsearch.md.erb +18 -32
  27. data/docs/resources/etc_fstab.md.erb +19 -15
  28. data/docs/resources/etc_group.md.erb +13 -39
  29. data/docs/resources/etc_hosts.md.erb +12 -5
  30. data/docs/resources/etc_hosts_allow.md.erb +9 -4
  31. data/docs/resources/etc_hosts_deny.md.erb +12 -7
  32. data/docs/resources/file.md.erb +139 -134
  33. data/docs/resources/filesystem.md.erb +5 -4
  34. data/docs/resources/firewalld.md.erb +1 -1
  35. data/docs/resources/gem.md.erb +2 -2
  36. data/docs/resources/group.md.erb +1 -1
  37. data/docs/resources/host.md.erb +1 -1
  38. data/docs/resources/iis_app.md.erb +1 -1
  39. data/docs/resources/iis_site.md.erb +1 -1
  40. data/docs/resources/interface.md.erb +1 -1
  41. data/docs/resources/iptables.md.erb +1 -1
  42. data/docs/resources/json.md.erb +1 -1
  43. data/docs/resources/kernel_module.md.erb +1 -1
  44. data/docs/resources/kernel_parameter.md.erb +1 -1
  45. data/docs/resources/launchd_service.md.erb +1 -1
  46. data/docs/resources/limits_conf.md.erb +1 -1
  47. data/docs/resources/login_def.md.erb +1 -1
  48. data/docs/resources/mount.md.erb +1 -1
  49. data/docs/resources/mysql_conf.md.erb +1 -1
  50. data/docs/resources/nginx_conf.md.erb +1 -1
  51. data/docs/resources/npm.md.erb +1 -1
  52. data/docs/resources/oneget.md.erb +1 -1
  53. data/docs/resources/os.md.erb +1 -1
  54. data/docs/resources/os_env.md.erb +2 -2
  55. data/docs/resources/package.md.erb +1 -1
  56. data/docs/resources/packages.md.erb +66 -0
  57. data/docs/resources/parse_config.md.erb +1 -1
  58. data/docs/resources/parse_config_file.md.erb +1 -1
  59. data/docs/resources/passwd.md.erb +1 -1
  60. data/docs/resources/pip.md.erb +1 -1
  61. data/docs/resources/port.md.erb +1 -1
  62. data/docs/resources/postgres_conf.md.erb +1 -1
  63. data/docs/resources/postgres_session.md.erb +1 -1
  64. data/docs/resources/powershell.md.erb +2 -2
  65. data/docs/resources/processes.md.erb +1 -1
  66. data/docs/resources/registry_key.md.erb +1 -1
  67. data/docs/resources/runit_service.md.erb +1 -1
  68. data/docs/resources/security_policy.md.erb +1 -1
  69. data/docs/resources/service.md.erb +1 -1
  70. data/docs/resources/shadow.md.erb +1 -1
  71. data/docs/resources/ssh_config.md.erb +1 -1
  72. data/docs/resources/sshd_config.md.erb +1 -1
  73. data/docs/resources/ssl.md.erb +1 -1
  74. data/docs/resources/sys_info.md.erb +1 -1
  75. data/docs/resources/systemd_service.md.erb +1 -1
  76. data/docs/resources/sysv_service.md.erb +1 -1
  77. data/docs/resources/upstart_service.md.erb +1 -1
  78. data/docs/resources/user.md.erb +1 -1
  79. data/docs/resources/users.md.erb +1 -1
  80. data/docs/resources/windows_feature.md.erb +1 -1
  81. data/docs/resources/windows_hotfix.md.erb +1 -1
  82. data/docs/resources/xinetd_conf.md.erb +1 -1
  83. data/docs/resources/xml.md.erb +1 -1
  84. data/docs/resources/yaml.md.erb +1 -1
  85. data/docs/resources/yum.md.erb +1 -1
  86. data/lib/inspec.rb +2 -1
  87. data/lib/inspec/base_cli.rb +98 -18
  88. data/lib/inspec/cli.rb +33 -21
  89. data/lib/inspec/formatters.rb +3 -0
  90. data/lib/inspec/formatters/base.rb +208 -0
  91. data/lib/inspec/formatters/json_rspec.rb +20 -0
  92. data/lib/inspec/formatters/show_progress.rb +12 -0
  93. data/lib/inspec/objects.rb +1 -0
  94. data/lib/inspec/objects/describe.rb +92 -0
  95. data/lib/inspec/reporters.rb +33 -0
  96. data/lib/inspec/reporters/base.rb +23 -0
  97. data/lib/inspec/reporters/cli.rb +395 -0
  98. data/lib/inspec/reporters/json.rb +132 -0
  99. data/lib/inspec/reporters/json_min.rb +44 -0
  100. data/lib/inspec/reporters/junit.rb +77 -0
  101. data/lib/inspec/runner.rb +14 -1
  102. data/lib/inspec/runner_rspec.rb +34 -14
  103. data/lib/inspec/schema.rb +1 -0
  104. data/lib/inspec/shell.rb +0 -1
  105. data/lib/inspec/version.rb +1 -1
  106. data/lib/resources/apache.rb +20 -0
  107. data/lib/resources/apache_conf.rb +33 -8
  108. data/lib/resources/audit_policy.rb +1 -1
  109. data/lib/resources/packages.rb +4 -3
  110. metadata +17 -4
  111. data/lib/inspec/rspec_json_formatter.rb +0 -940
@@ -0,0 +1,132 @@
1
+ # encoding: utf-8
2
+
3
+ require 'json'
4
+
5
+ module Inspec::Reporters
6
+ class Json < Base
7
+ def render
8
+ report = {
9
+ platform: platform,
10
+ profiles: profiles,
11
+ statistics: { duration: run_data[:statistics][:duration] },
12
+ version: run_data[:version],
13
+ controls: controls,
14
+ other_checks: run_data[:other_checks],
15
+ }
16
+
17
+ output(report.to_json)
18
+ end
19
+
20
+ private
21
+
22
+ def platform
23
+ {
24
+ name: run_data[:platform][:name],
25
+ release: run_data[:platform][:release],
26
+ }
27
+ end
28
+
29
+ def controls
30
+ controls = []
31
+ return controls if run_data[:controls].nil?
32
+
33
+ run_data[:controls].each do |c|
34
+ control = {
35
+ status: c[:status],
36
+ start_time: c[:start_time],
37
+ run_time: c[:run_time],
38
+ code_desc: c[:code_desc],
39
+ }
40
+ control[:resource] = c[:resource] if c[:resource]
41
+ control[:skip_message] = c[:skip_message] if c[:skip_message]
42
+ control[:exception] = c[:exception] if c[:exception]
43
+ control[:backtrace] = c[:backtrace] if c[:backtrace]
44
+
45
+ controls << control
46
+ end
47
+ controls
48
+ end
49
+
50
+ def profile_results(control)
51
+ results = []
52
+ return results if control[:results].nil?
53
+
54
+ control[:results].each do |r|
55
+ result = {
56
+ status: r[:status],
57
+ code_desc: r[:code_desc],
58
+ run_time: r[:run_time],
59
+ start_time: r[:start_time],
60
+ }
61
+ result[:resource] = r[:resource] if r[:resource]
62
+ result[:skip_message] = r[:skip_message] if r[:skip_message]
63
+
64
+ results << result
65
+ end
66
+ results
67
+ end
68
+
69
+ def profile_controls(profile)
70
+ controls = []
71
+ return controls if profile[:controls].nil?
72
+
73
+ profile[:controls].each do |c|
74
+ control = {
75
+ id: c[:id],
76
+ title: c[:title],
77
+ desc: c[:desc],
78
+ impact: c[:impact],
79
+ refs: c[:refs],
80
+ tags: c[:tags],
81
+ code: c[:code],
82
+ source_location: {
83
+ line: c[:source_location][:line],
84
+ ref: c[:source_location][:ref],
85
+ },
86
+ results: profile_results(c),
87
+ }
88
+ controls << control
89
+ end
90
+ controls
91
+ end
92
+
93
+ def profile_groups(profile)
94
+ groups = []
95
+ return groups if profile[:groups].nil?
96
+
97
+ profile[:groups].each do |g|
98
+ group = {
99
+ id: g[:id],
100
+ controls: g[:controls],
101
+ }
102
+ group[:title] = g[:title] if g[:title]
103
+
104
+ groups << group
105
+ end
106
+ groups
107
+ end
108
+
109
+ def profiles
110
+ profiles = []
111
+ run_data[:profiles].each do |p|
112
+ profile = {
113
+ name: p[:name],
114
+ version: p[:version],
115
+ sha256: p[:sha256],
116
+ title: p[:title],
117
+ maintainer: p[:maintainer],
118
+ summary: p[:summary],
119
+ license: p[:license],
120
+ copyright: p[:copyright],
121
+ copyright_email: p[:copyright_email],
122
+ supports: p[:supports],
123
+ attributes: p[:attributes],
124
+ groups: profile_groups(p),
125
+ controls: profile_controls(p),
126
+ }
127
+ profiles << profile.reject { |_k, v| v.nil? }
128
+ end
129
+ profiles
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ require 'json'
4
+
5
+ module Inspec::Reporters
6
+ class JsonMin < Base
7
+ def render # rubocop:disable Metrics/AbcSize
8
+ report = {
9
+ controls: [],
10
+ statistics: { duration: run_data[:statistics][:duration] },
11
+ version: run_data[:version],
12
+ }
13
+
14
+ # collect all test results and add them to the report
15
+ run_data[:profiles].each do |profile|
16
+ profile_id = profile[:name]
17
+ next unless profile[:controls]
18
+ profile[:controls].each do |control|
19
+ control_id = control[:id]
20
+ next unless control[:results]
21
+ control[:results].each do |result|
22
+ result_for_report = {
23
+ id: control_id,
24
+ profile_id: profile_id,
25
+ profile_sha256: profile[:sha256],
26
+ status: result[:status],
27
+ code_desc: result[:code_desc],
28
+ }
29
+
30
+ result_for_report[:skip_message] = result[:skip_message] if result.key?(:skip_message)
31
+ result_for_report[:resource] = result[:resource] if result.key?(:resource)
32
+ result_for_report[:message] = result[:message] if result.key?(:message)
33
+ result_for_report[:exception] = result[:exception] if result.key?(:exception)
34
+ result_for_report[:backtrace] = result[:backtrace] if result.key?(:backtrace)
35
+
36
+ report[:controls] << result_for_report
37
+ end
38
+ end
39
+ end
40
+
41
+ output(report.to_json)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+
3
+ module Inspec::Reporters
4
+ class Junit < Base
5
+ def render
6
+ require 'rexml/document'
7
+ xml_output = REXML::Document.new
8
+ xml_output.add(REXML::XMLDecl.new)
9
+
10
+ testsuites = REXML::Element.new('testsuites')
11
+ xml_output.add(testsuites)
12
+
13
+ run_data[:profiles].each do |profile|
14
+ testsuites.add(build_profile_xml(profile))
15
+ end
16
+
17
+ formatter = REXML::Formatters::Pretty.new
18
+ formatter.compact = true
19
+ output(formatter.write(xml_output.xml_decl, ''))
20
+ output(formatter.write(xml_output.root, ''))
21
+ end
22
+
23
+ private
24
+
25
+ def build_profile_xml(profile)
26
+ profile_xml = REXML::Element.new('testsuite')
27
+ profile_xml.add_attribute('name', profile[:name])
28
+ profile_xml.add_attribute('tests', count_profile_tests(profile))
29
+ profile_xml.add_attribute('failed', count_profile_failed_tests(profile))
30
+
31
+ profile[:controls].each do |control|
32
+ next if control[:results].nil?
33
+
34
+ control[:results].each do |result|
35
+ profile_xml.add(build_result_xml(profile[:name], control, result))
36
+ end
37
+ end
38
+
39
+ profile_xml
40
+ end
41
+
42
+ def build_result_xml(profile_name, control, result)
43
+ result_xml = REXML::Element.new('testcase')
44
+ result_xml.add_attribute('name', result[:code_desc])
45
+ result_xml.add_attribute('classname', control[:title].nil? ? "#{profile_name}.Anonymous" : "#{profile_name}.#{control[:id]}")
46
+ result_xml.add_attribute('time', result[:run_time])
47
+
48
+ if result[:status] == 'failed'
49
+ failure_element = REXML::Element.new('failure')
50
+ failure_element.add_attribute('message', result[:message])
51
+ result_xml.add(failure_element)
52
+ elsif result[:status] == 'skipped'
53
+ result_xml.add_element('skipped')
54
+ end
55
+
56
+ result_xml
57
+ end
58
+
59
+ def count_profile_tests(profile)
60
+ profile[:controls].reduce(0) { |acc, elem|
61
+ acc + (elem[:results].nil? ? 0 : elem[:results].count)
62
+ }
63
+ end
64
+
65
+ def count_profile_failed_tests(profile)
66
+ profile[:controls].reduce(0) { |acc, elem|
67
+ if elem[:results].nil?
68
+ acc
69
+ else
70
+ acc + elem[:results].reduce(0) { |fail_test_total, test_case|
71
+ test_case[:status] == 'failed' ? fail_test_total + 1 : fail_test_total
72
+ }
73
+ end
74
+ }
75
+ end
76
+ end
77
+ end
@@ -49,6 +49,9 @@ module Inspec
49
49
  RunnerRspec.new(@conf)
50
50
  end
51
51
 
52
+ # parse any ad-hoc runners reporter formats
53
+ @conf = Inspec::BaseCLI.parse_reporters(@conf) if @conf[:type].nil?
54
+
52
55
  # list of profile attributes
53
56
  @attributes = []
54
57
 
@@ -101,6 +104,14 @@ module Inspec
101
104
  run_tests(with)
102
105
  end
103
106
 
107
+ def render_output(run_data)
108
+ return if @conf['reporter'].nil?
109
+
110
+ @conf['reporter'].each do |reporter|
111
+ Inspec::Reporters.render(reporter, run_data)
112
+ end
113
+ end
114
+
104
115
  def write_lockfile(profile)
105
116
  return false if !profile.writable?
106
117
 
@@ -114,7 +125,9 @@ module Inspec
114
125
  end
115
126
 
116
127
  def run_tests(with = nil)
117
- @test_collector.run(with)
128
+ status, run_data = @test_collector.run(with)
129
+ render_output(run_data)
130
+ status
118
131
  end
119
132
 
120
133
  # determine all attributes before the execution, fetch data from secrets backend
@@ -4,7 +4,7 @@
4
4
 
5
5
  require 'rspec/core'
6
6
  require 'rspec/its'
7
- require 'inspec/rspec_json_formatter'
7
+ require 'inspec/formatters'
8
8
 
9
9
  # There be dragons!! Or borgs, or something...
10
10
  # This file and all its contents cannot be unit-tested. both test-suits
@@ -33,7 +33,7 @@ module Inspec
33
33
  # @return [nil]
34
34
  def add_profile(profile)
35
35
  RSpec.configuration.formatters
36
- .find_all { |c| c.is_a? InspecRspecJson }
36
+ .find_all { |c| c.is_a?(Inspec::Formatters::Base) }
37
37
  .each do |fmt|
38
38
  fmt.add_profile(profile)
39
39
  end
@@ -45,7 +45,7 @@ module Inspec
45
45
  # @return [nil]
46
46
  def backend=(backend)
47
47
  RSpec.configuration.formatters
48
- .find_all { |c| c.is_a? InspecRspecJson }
48
+ .find_all { |c| c.is_a?(Inspec::Formatters::Base) }
49
49
  .each do |fmt|
50
50
  fmt.backend = backend
51
51
  end
@@ -74,7 +74,8 @@ module Inspec
74
74
  # @return [int] 0 if all went well; otherwise nonzero
75
75
  def run(with = nil)
76
76
  with ||= RSpec::Core::Runner.new(nil)
77
- with.run_specs(tests)
77
+ status = with.run_specs(tests)
78
+ [status, @formatter.run_data]
78
79
  end
79
80
 
80
81
  # Provide an output hash of the run's report
@@ -98,13 +99,32 @@ module Inspec
98
99
 
99
100
  private
100
101
 
101
- FORMATTERS = {
102
- 'json-min' => 'InspecRspecMiniJson',
103
- 'json' => 'InspecRspecJson',
104
- 'json-rspec' => 'InspecRspecVanilla',
105
- 'cli' => 'InspecRspecCli',
106
- 'junit' => 'InspecRspecJUnit',
107
- }.freeze
102
+ # Set optional formatters and output
103
+ #
104
+ #
105
+ def set_optional_formatters
106
+ return if @conf[:reporter].nil?
107
+ if @conf[:reporter].key?('json-rspec')
108
+ # We cannot pass in a nil output path. Rspec only accepts a valid string or a IO object.
109
+ if @conf[:reporter]['json-rspec']&.[]('file').nil?
110
+ RSpec.configuration.add_formatter(Inspec::Formatters::RspecJson)
111
+ else
112
+ RSpec.configuration.add_formatter(Inspec::Formatters::RspecJson, @conf[:reporter]['json-rspec']['file'])
113
+ end
114
+ @conf[:reporter].delete('json-rspec')
115
+ end
116
+
117
+ formats = @conf[:reporter].select { |k, _v| %w{documentation progress html}.include?(k) }
118
+ formats.each do |k, v|
119
+ # We cannot pass in a nil output path. Rspec only accepts a valid string or a IO object.
120
+ if v&.[]('file').nil?
121
+ RSpec.configuration.add_formatter(k.to_sym)
122
+ else
123
+ RSpec.configuration.add_formatter(k.to_sym, v['file'])
124
+ end
125
+ @conf[:reporter].delete(k)
126
+ end
127
+ end
108
128
 
109
129
  # Configure the output formatter and stream to be used with RSpec.
110
130
  #
@@ -116,10 +136,10 @@ module Inspec
116
136
  RSpec.configuration.output_stream = @conf['output']
117
137
  end
118
138
 
119
- format = FORMATTERS[@conf['format']] || @conf['format'] || FORMATTERS['cli']
120
- @formatter = RSpec.configuration.add_formatter(format)
139
+ @formatter = RSpec.configuration.add_formatter(Inspec::Formatters::Base)
140
+ RSpec.configuration.add_formatter(Inspec::Formatters::ShowProgress, $stderr) if @conf[:show_progress]
141
+ set_optional_formatters
121
142
  RSpec.configuration.color = @conf['color']
122
-
123
143
  setup_reporting if @conf['report']
124
144
  end
125
145
 
@@ -147,6 +147,7 @@ module Inspec
147
147
  'properties' => {
148
148
  'id' => { 'type' => 'string' },
149
149
  'profile_id' => { 'type' => %w{string null} },
150
+ 'profile_sha256' => { 'type' => 'string' },
150
151
  'status' => { 'type' => 'string' },
151
152
  'code_desc' => { 'type' => 'string' },
152
153
  'skip_message' => { 'type' => 'string', 'optional' => true },
@@ -2,7 +2,6 @@
2
2
  # author: Dominik Richter
3
3
  # author: Christoph Hartmann
4
4
 
5
- require 'rspec/core/formatters/base_text_formatter'
6
5
  require 'pry'
7
6
 
8
7
  module Inspec
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.51.0'
7
+ VERSION = '1.51.6'
8
8
  end
@@ -6,9 +6,29 @@
6
6
  module Inspec::Resources
7
7
  class Apache < Inspec.resource(1)
8
8
  name 'apache'
9
+ desc 'Use the apache InSpec audit resource to retrieve Apache environment settings.'
10
+ example "
11
+ describe apache do
12
+ its ('service') { should cmp 'apache2' }
13
+ end
14
+
15
+ describe apache do
16
+ its ('conf_dir') { should cmp '/etc/apache2' }
17
+ end
18
+
19
+ describe apache do
20
+ its ('conf_path') { should cmp '/etc/apache2/apache2.conf' }
21
+ end
22
+
23
+ describe apache do
24
+ its ('user') { should cmp 'www-data' }
25
+ end
26
+ "
9
27
 
10
28
  attr_reader :service, :conf_dir, :conf_path, :user
11
29
  def initialize
30
+ warn '[DEPRECATED] The `apache` resource is deprecated and will be removed in InSpec 3.0.'
31
+
12
32
  if inspec.os.debian?
13
33
  @service = 'apache2'
14
34
  @conf_dir = '/etc/apache2/'
@@ -9,6 +9,8 @@ require 'utils/find_files'
9
9
  module Inspec::Resources
10
10
  class ApacheConf < Inspec.resource(1)
11
11
  name 'apache_conf'
12
+ supports os_family: 'linux'
13
+ supports os_family: 'debian'
12
14
  desc 'Use the apache_conf InSpec audit resource to test the configuration settings for Apache. This file is typically located under /etc/apache2 on the Debian and Ubuntu platforms and under /etc/httpd on the Fedora, CentOS, Red Hat Enterprise Linux, and Arch Linux platforms. The configuration settings may vary significantly from platform to platform.'
13
15
  example "
14
16
  describe apache_conf do
@@ -18,9 +20,10 @@ module Inspec::Resources
18
20
 
19
21
  include FindFiles
20
22
 
23
+ attr_reader :conf_path
24
+
21
25
  def initialize(conf_path = nil)
22
- @conf_path = conf_path || inspec.apache.conf_path
23
- @conf_dir = conf_path ? File.dirname(@conf_path) : inspec.apache.conf_dir
26
+ @conf_path = conf_path || default_conf_path
24
27
  @files_contents = {}
25
28
  @content = nil
26
29
  @params = nil
@@ -63,17 +66,17 @@ module Inspec::Resources
63
66
  @params = {}
64
67
 
65
68
  # skip if the main configuration file doesn't exist
66
- file = inspec.file(@conf_path)
69
+ file = inspec.file(conf_path)
67
70
  if !file.file?
68
- return skip_resource "Can't find file \"#{@conf_path}\""
71
+ return skip_resource "Can't find file \"#{conf_path}\""
69
72
  end
70
73
 
71
74
  raw_conf = file.content
72
75
  if raw_conf.empty? && !file.empty?
73
- return skip_resource("Can't read file \"#{@conf_path}\"")
76
+ return skip_resource("Can't read file \"#{conf_path}\"")
74
77
  end
75
78
 
76
- to_read = [@conf_path]
79
+ to_read = [conf_path]
77
80
  until to_read.empty?
78
81
  raw_conf = read_file(to_read[0])
79
82
  @content += raw_conf
@@ -111,7 +114,7 @@ module Inspec::Resources
111
114
 
112
115
  includes = []
113
116
  (include_files + include_files_optional).each do |f|
114
- id = Pathname.new(f).absolute? ? f : File.join(@conf_dir, f)
117
+ id = Pathname.new(f).absolute? ? f : File.join(conf_dir, f)
115
118
  files = find_files(id, depth: 1, type: 'file')
116
119
  files += find_files(id, depth: 1, type: 'link')
117
120
 
@@ -126,8 +129,30 @@ module Inspec::Resources
126
129
  @files_contents[path] ||= inspec.file(path).content
127
130
  end
128
131
 
132
+ def conf_dir
133
+ if inspec.os.debian?
134
+ File.dirname(conf_path)
135
+ else
136
+ # On RHEL-based systems, the configuration is usually in a /conf directory
137
+ # that contains the primary config file. We assume the "config path" is the
138
+ # directory that contains the /conf directory, such as /etc/httpd, so that
139
+ # the conf.d directory can be properly located.
140
+ Pathname.new(File.dirname(conf_path)).parent.to_s
141
+ end
142
+ end
143
+
129
144
  def to_s
130
- "Apache Config #{@conf_path}"
145
+ "Apache Config #{conf_path}"
146
+ end
147
+
148
+ private
149
+
150
+ def default_conf_path
151
+ if inspec.os.debian?
152
+ '/etc/apache2/apache2.conf'
153
+ else
154
+ '/etc/httpd/conf/httpd.conf'
155
+ end
131
156
  end
132
157
  end
133
158
  end