InSpec Examples
InSpec Examples
RSpec Explicit Subject
Here we have an InSpec test that lists out its current directory. Our original test code looks like this:
describe command('ls -al').stdout.strip do
it { should_not be_empty }
end
If we would like to have a more detailed feedback to our user, we can override the standard title of our describe block with a specific message that describes the intent of the test and use the Explicit Subject to tell inspec what the "subject" is for the test, then, we could refactor the code like this:
describe "this is a detailed message" do
subject { command('ls -al').stdout.strip }
it{ should_not be_empty }
end
Looping Through Data
The file
resource is perfect for looking at single files and thier properities, however, it does not look at groups of files. To do that we need to use multiple resources in concert. Let's use the command
resource to run the find
command, or it's equivalent for your target OS, and then use the file
resource. Using multiple resources together is one of the key values InSpec provides, allowing you get get at just the data you need when you need it.
Avoid Large Sets or 'Check Everyone at the Door' Approaches
For IO intensive (full filesystem, or global scans) or large scale processes, try to be as specific as possible with your searches. Think about using 'negitive logic' vs 'positive logic' - "Find me all the items outside my target set" vs "Look at each item in the set and ensure it has these propertiies".
This 'find the outsiders' vs 'check everyone at the door' approach can really speed things along. Again, keep your data set as small as possible, don't inspect more then the requirements, well, requires.
command('find ~/* -type f -maxdepth 0 -xdev').stdout.split.each do |fname|
describe file(fname) do
its('owner') { should cmp 'ec2-user' }
end
end
should
vs. expect
syntax
The Users familiar with the rSpec testing framework may know that there are two ways to write test statements: should
and expect
. The RSpec community decided that expect
is the preferred syntax.
InSpec recommends the should
syntax as it tends to read more easily to those users who are not as technical, however there are times when the expect
syntax will communicate much more clearly to the end-user.
InSpec will continue to support both methods of writing tests. Consider this file test:
describe file('/tmp/test.txt') do
it { should be_file }
end
This can be re-written with expect syntax
describe file('/tmp/test.txt') do
it 'should be a file' do
expect(subject).to(be_file)
end
end
The output of both of the above examples looks like this:
File /tmp/test.txt
✔ should be a file
In addition, you can make use of the subject
keyword to further control your output if you choose:
describe 'test file' do
subject { file('/tmp/test.txt') }
it 'should be a file' do
expect(subject).to(be_file)
end
end
… which will render the following output:
test file
✔ should be a file
Reference: https://docs.chef.io/inspec/profiles/
Expect
syntax and Password Hashes
Here we have an inspec test that checks if passwords are SHA512 hashes. As a quick thought exercise, can you think of how we can adjust the control below to support SHA512 or higher assuming where you are testing uses SHA1024 or even SHA2048?
As we said, when possible, and when there is a high change of a large set only having a few offending items, attempt to find only those items that could be outside our requirements, if there are none, wonderful, we met our requirement.
bad_users = inspec.shadow.where { password != "*" && password != "!" && password !~ /\$6\$/ }.users
describe 'Password hashes in /etc/shadow' do
it 'should only contain SHA512 hashes' do
failure_message = "Users without SHA512 hashes: #{bad_users.join(', ')}"
expect(bad_users).to be_empty, failure_message
end
end