inspec 1.51.0 → 1.51.6
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 +4 -4
- data/CHANGELOG.md +29 -15
- data/README.md +1 -1
- data/docs/glossary.md +99 -0
- data/docs/resources/aide_conf.md.erb +16 -9
- data/docs/resources/apache.md.erb +66 -0
- data/docs/resources/apache_conf.md.erb +11 -5
- data/docs/resources/apt.md.erb +1 -1
- data/docs/resources/audit_policy.md.erb +1 -1
- data/docs/resources/auditd_conf.md.erb +12 -9
- data/docs/resources/bash.md.erb +24 -12
- data/docs/resources/bond.md.erb +26 -24
- data/docs/resources/bridge.md.erb +18 -11
- data/docs/resources/bsd_service.md.erb +11 -2
- data/docs/resources/command.md.erb +30 -29
- data/docs/resources/cpan.md.erb +33 -17
- data/docs/resources/cran.md.erb +26 -17
- data/docs/resources/crontab.md.erb +18 -1
- data/docs/resources/csv.md.erb +13 -7
- data/docs/resources/{dh_params.md → dh_params.md.erb} +30 -6
- data/docs/resources/directory.md.erb +9 -4
- data/docs/resources/docker.md.erb +1 -1
- data/docs/resources/docker_container.md.erb +32 -26
- data/docs/resources/docker_image.md.erb +29 -26
- data/docs/resources/docker_service.md.erb +37 -31
- data/docs/resources/elasticsearch.md.erb +18 -32
- data/docs/resources/etc_fstab.md.erb +19 -15
- data/docs/resources/etc_group.md.erb +13 -39
- data/docs/resources/etc_hosts.md.erb +12 -5
- data/docs/resources/etc_hosts_allow.md.erb +9 -4
- data/docs/resources/etc_hosts_deny.md.erb +12 -7
- data/docs/resources/file.md.erb +139 -134
- data/docs/resources/filesystem.md.erb +5 -4
- data/docs/resources/firewalld.md.erb +1 -1
- data/docs/resources/gem.md.erb +2 -2
- data/docs/resources/group.md.erb +1 -1
- data/docs/resources/host.md.erb +1 -1
- data/docs/resources/iis_app.md.erb +1 -1
- data/docs/resources/iis_site.md.erb +1 -1
- data/docs/resources/interface.md.erb +1 -1
- data/docs/resources/iptables.md.erb +1 -1
- data/docs/resources/json.md.erb +1 -1
- data/docs/resources/kernel_module.md.erb +1 -1
- data/docs/resources/kernel_parameter.md.erb +1 -1
- data/docs/resources/launchd_service.md.erb +1 -1
- data/docs/resources/limits_conf.md.erb +1 -1
- data/docs/resources/login_def.md.erb +1 -1
- data/docs/resources/mount.md.erb +1 -1
- data/docs/resources/mysql_conf.md.erb +1 -1
- data/docs/resources/nginx_conf.md.erb +1 -1
- data/docs/resources/npm.md.erb +1 -1
- data/docs/resources/oneget.md.erb +1 -1
- data/docs/resources/os.md.erb +1 -1
- data/docs/resources/os_env.md.erb +2 -2
- data/docs/resources/package.md.erb +1 -1
- data/docs/resources/packages.md.erb +66 -0
- data/docs/resources/parse_config.md.erb +1 -1
- data/docs/resources/parse_config_file.md.erb +1 -1
- data/docs/resources/passwd.md.erb +1 -1
- data/docs/resources/pip.md.erb +1 -1
- data/docs/resources/port.md.erb +1 -1
- data/docs/resources/postgres_conf.md.erb +1 -1
- data/docs/resources/postgres_session.md.erb +1 -1
- data/docs/resources/powershell.md.erb +2 -2
- data/docs/resources/processes.md.erb +1 -1
- data/docs/resources/registry_key.md.erb +1 -1
- data/docs/resources/runit_service.md.erb +1 -1
- data/docs/resources/security_policy.md.erb +1 -1
- data/docs/resources/service.md.erb +1 -1
- data/docs/resources/shadow.md.erb +1 -1
- data/docs/resources/ssh_config.md.erb +1 -1
- data/docs/resources/sshd_config.md.erb +1 -1
- data/docs/resources/ssl.md.erb +1 -1
- data/docs/resources/sys_info.md.erb +1 -1
- data/docs/resources/systemd_service.md.erb +1 -1
- data/docs/resources/sysv_service.md.erb +1 -1
- data/docs/resources/upstart_service.md.erb +1 -1
- data/docs/resources/user.md.erb +1 -1
- data/docs/resources/users.md.erb +1 -1
- data/docs/resources/windows_feature.md.erb +1 -1
- data/docs/resources/windows_hotfix.md.erb +1 -1
- data/docs/resources/xinetd_conf.md.erb +1 -1
- data/docs/resources/xml.md.erb +1 -1
- data/docs/resources/yaml.md.erb +1 -1
- data/docs/resources/yum.md.erb +1 -1
- data/lib/inspec.rb +2 -1
- data/lib/inspec/base_cli.rb +98 -18
- data/lib/inspec/cli.rb +33 -21
- data/lib/inspec/formatters.rb +3 -0
- data/lib/inspec/formatters/base.rb +208 -0
- data/lib/inspec/formatters/json_rspec.rb +20 -0
- data/lib/inspec/formatters/show_progress.rb +12 -0
- data/lib/inspec/objects.rb +1 -0
- data/lib/inspec/objects/describe.rb +92 -0
- data/lib/inspec/reporters.rb +33 -0
- data/lib/inspec/reporters/base.rb +23 -0
- data/lib/inspec/reporters/cli.rb +395 -0
- data/lib/inspec/reporters/json.rb +132 -0
- data/lib/inspec/reporters/json_min.rb +44 -0
- data/lib/inspec/reporters/junit.rb +77 -0
- data/lib/inspec/runner.rb +14 -1
- data/lib/inspec/runner_rspec.rb +34 -14
- data/lib/inspec/schema.rb +1 -0
- data/lib/inspec/shell.rb +0 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/apache.rb +20 -0
- data/lib/resources/apache_conf.rb +33 -8
- data/lib/resources/audit_policy.rb +1 -1
- data/lib/resources/packages.rb +4 -3
- metadata +17 -4
- 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
|
data/lib/inspec/runner.rb
CHANGED
@@ -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
|
data/lib/inspec/runner_rspec.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
require 'rspec/core'
|
6
6
|
require 'rspec/its'
|
7
|
-
require 'inspec/
|
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?
|
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?
|
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
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
120
|
-
|
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
|
|
data/lib/inspec/schema.rb
CHANGED
@@ -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 },
|
data/lib/inspec/shell.rb
CHANGED
data/lib/inspec/version.rb
CHANGED
data/lib/resources/apache.rb
CHANGED
@@ -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 ||
|
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(
|
69
|
+
file = inspec.file(conf_path)
|
67
70
|
if !file.file?
|
68
|
-
return skip_resource "Can't find file \"#{
|
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 \"#{
|
76
|
+
return skip_resource("Can't read file \"#{conf_path}\"")
|
74
77
|
end
|
75
78
|
|
76
|
-
to_read = [
|
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(
|
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 #{
|
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
|