inspec 1.51.0 → 1.51.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|