1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
require "spec_helper"
describe Chef::Compliance::Runner do
let(:logger) { double(:logger).as_null_object }
let(:node) { Chef::Node.new(logger: logger) }
let(:runner) do
described_class.new.tap do |r|
r.node = node
r.run_id = "my_run_id"
end
end
describe "#enabled?" do
it "is true if the node attributes have audit profiles and the audit cookbook is not present" do
node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
expect(runner).to be_enabled
end
it "is false if the node attributes have audit profiles and the audit cookbook is not present, and the compliance mode attribute is unset" do
node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
node.normal["audit"]["compliance_mode"] = false
expect(runner).to be_enabled
end
it "is false if the node attributes have audit profiles and the audit cookbook is present" do
stub_const("::Reporter::ChefAutomate", true)
node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
expect(runner).not_to be_enabled
end
it "is false if the node attributes do not have audit profiles and the audit cookbook is not present" do
node.normal["audit"]["profiles"] = {}
expect(runner).not_to be_enabled
end
it "is false if the node attributes do not have audit profiles and the audit cookbook is present" do
stub_const("::Reporter::ChefAutomate", true)
node.automatic["recipes"] = %w{ audit::default fancy_cookbook::fanciness tacobell::nachos }
expect(runner).not_to be_enabled
end
it "is false if the node attributes do not have audit attributes and the audit cookbook is not present" do
node.automatic["recipes"] = %w{ fancy_cookbook::fanciness tacobell::nachos }
expect(runner).not_to be_enabled
end
end
describe "#inspec_profiles" do
it "returns an empty list with no profiles defined" do
expect(runner.inspec_profiles).to eq([])
end
it "converts from the attribute format to the format Inspec expects" do
node.normal["audit"]["profiles"]["linux-baseline"] = {
'compliance': "user/linux-baseline",
'version': "2.1.0",
}
node.normal["audit"]["profiles"]["ssh"] = {
'supermarket': "hardening/ssh-hardening",
}
expected = [
{
compliance: "user/linux-baseline",
name: "linux-baseline",
version: "2.1.0",
},
{
name: "ssh",
supermarket: "hardening/ssh-hardening",
},
]
expect(runner.inspec_profiles).to eq(expected)
end
it "raises an error when the profiles are in the old audit-cookbook format" do
node.normal["audit"]["profiles"] = [
{
name: "Windows 2019 Baseline",
compliance: "admin/windows-2019-baseline",
},
]
expect { runner.inspec_profiles }.to raise_error(/profiles specified in an unrecognized format, expected a hash of hashes./)
end
end
describe "#warn_for_deprecated_config_values!" do
it "logs a warning when deprecated config values are present" do
node.normal["audit"]["owner"] = "my_org"
node.normal["audit"]["inspec_version"] = "90210"
expect(logger).to receive(:warn).with(/config values 'inspec_version', 'owner' are not supported/)
runner.warn_for_deprecated_config_values!
end
it "does not log a warning with no deprecated config values" do
node.normal["audit"]["profiles"]["linux-baseline"] = {
'compliance': "user/linux-baseline",
'version': "2.1.0",
}
expect(logger).not_to receive(:warn)
runner.warn_for_deprecated_config_values!
end
end
describe "#reporter" do
context "chef-server-automate reporter" do
it "uses the correct URL when 'server' attribute is set" do
Chef::Config[:chef_server_url] = "https://chef_config_url.example.com/my_org"
node.normal["audit"]["server"] = "https://server_attribute_url.example.com/application/sub_application"
reporter = runner.reporter("chef-server-automate")
expect(reporter).to be_kind_of(Chef::Compliance::Reporter::ChefServerAutomate)
expect(reporter.url).to eq(URI("https://server_attribute_url.example.com/application/sub_application/organizations/my_org/data-collector"))
end
it "falls back to chef_server_url for URL when 'server' attribute is not set" do
Chef::Config[:chef_server_url] = "https://chef_config_url.example.com/my_org"
reporter = runner.reporter("chef-server-automate")
expect(reporter).to be_kind_of(Chef::Compliance::Reporter::ChefServerAutomate)
expect(reporter.url).to eq(URI("https://chef_config_url.example.com/organizations/my_org/data-collector"))
end
end
it "fails with unexpected reporter value" do
expect { runner.reporter("tacos") }.to raise_error(/'tacos' is not a supported reporter for Compliance Phase/)
end
end
describe "#inspec_opts" do
it "does not include chef_node in inputs by default" do
node.normal["audit"]["attributes"] = {
"tacos" => "lunch",
"nachos" => "dinner",
}
inputs = runner.inspec_opts[:inputs]
expect(inputs["tacos"]).to eq("lunch")
expect(inputs.key?("chef_node")).to eq(false)
end
it "includes chef_node in inputs with chef_node_attribute_enabled set" do
node.normal["audit"]["chef_node_attribute_enabled"] = true
node.normal["audit"]["attributes"] = {
"tacos" => "lunch",
"nachos" => "dinner",
}
inputs = runner.inspec_opts[:inputs]
expect(inputs["tacos"]).to eq("lunch")
expect(inputs["chef_node"]["audit"]["reporter"]).to eq("json-file")
expect(inputs["chef_node"]["chef_environment"]).to eq("_default")
end
end
end
|