inspec-gcp
inspec-gcp copied to clipboard
Fix (and / or spec help) with inspecting specific `compute_security_policy` rules
I'm trying to use the approaches described in https://megamorf.gitlab.io/cheat-sheets/inspec/ to inspect a specific compute policy. I've tried different ways to get it, but have had no luck so far.
Is there a currently supported way to do this?
If not implemented, could it be implemented? If it is implemented, could the docs be extended to provide an example (I can help with this part, if an example is given)
Describe the problem
The following code, as well as other things I've tried to accomplish similar things, does not seem to work:
describe google_compute_security_policy(project: PROJECT, name: 'kitchen-testpolicy') do
it { is_expected.to exist }
# Predictable because we're using the rules policy here
its('rules.size') { is_expected.to eq(6) }
its('rules.first.action') { is_expected.to eq('deny(403)') }
its('rules.first.priority') { is_expected.to eq(1001) }
describe 'rules.where(priority == 2000)' do
it { is_expected.to exist }
its('action') { is_expected.to eq('deny(403)') }
its('config.src_ip_ranges.size') { is_expected.to eq(8) }
its('config.src_ip_ranges.first') { is_expected.to eq('9.9.9.0/24') }
end
end
This throws an error like undefined method where...
and then prints out (typically) the entire object structure of the enclosing resource. I think this is because the rule itself isn't an inspec resource, and so there's no way to then describe the specific rule?
Using array slices (rules[2].action
, rules.at(2).action
) etc. doesn't seem to work either.
Possible Solution
Interestingly, I can't use shift(N)
, but I can use rules.shift
multiple times, and then refer to the new .first
, which doesn't read well, but works:
# Hacky way to get at other array slices
its('rules.shift.priority') { is_expected.to eq(1001) }
its('rules.shift.priority') { is_expected.to eq(1007) }
# "first" is now Nth
its('rules.first.description') { is_expected.to eq('Block IP ranges') }
its('rules.first.action') { is_expected.to eq('deny(403)') }
its('rules.first.match.config.src_ip_ranges.first') { is_expected.to eq('10.0.0.6/32') }
its('rules.first.match.config.src_ip_ranges.last') { is_expected.to eq('10.0.0.85/32') }
# Next IP block rule
its('rules.shift.priority') { is_expected.to eq(2000) }
its('rules.first.priority') { is_expected.to eq(2001) }
its('rules.first.match.config.src_ip_ranges.last') { is_expected.to eq('192.168.106.0/23') }
Got some tips on the Chef Slack. I think this is not an ideal way, but it does seem to work. Basically, if you assign to a variable, you can now use normal array methods.
control 'gcp_cloud_armor-1.0' do
kitchen_testpolicy = google_compute_security_policy(project: PROJECT, name: 'kitchen-testpolicy')
describe kitchen_testpolicy do
it { is_expected.to exist }
its('rules.size') { is_expected.to eq 8 }
rules = kitchen_testpolicy.rules
# Rules can now be tested by array slice, as well as by .first and .last
context 'when examining first WAF rule' do
describe rules[1] do
its('priority') { is_expected.to eq 1001 }
its('description') { is_expected.to eq 'Prevent Local File Inclusion Attacks' }
end
end
# [....]
context 'when examining second allowlist rule' do
describe rules[3] do
its('priority') { is_expected.to eq 11 }
its('action') { is_expected.to eq 'allow' }
its('match.config.src_ip_ranges.last') { is_expected.to eq '10.0.0.1/32' }
end
end
end
end