Studying an InSpec Profile
Studying an InSpec profile
Let's start by creating a profile that will contain NGINX tests.
At your terminal, type:
inspec init profile my_nginx
The terminal output should look like the following:
Create new profile at /root/my_nginx
* Create directory controls
* Create file controls/example.rb
* Create file inspec.yml
* Create directory libraries
* Create file README.md
Understanding the profile structure
Let's take a look at how the profile is structured. We'll start with how a profile's files are structured and then move to what makes up an InSpec control.
First, run tree
to see what's in the my_nginx
profile.
tree my_nginx
Which should look like:
my_nginx
βββ README.md
βββ controls
β βββ example.rb
βββ inspec.yml
1 directory, 3 files
Here's the role of each component.
README.md
provides documentation about the profile, including what it covers and how to run it.- The
controls
directory contains files which implement the InSpec tests. inspec.yml
provides metadata, or information, about the profile. Metadata includes the profile's description, author, copyright, and version.- The
libraries
directory contains resource extensions. A resource extension enables you to define your own resource types. You won't work with resource extensions in this module.
Understand a control's structure
Let's take a look at the default control file, controls/example.rb
.
title 'sample section'
# you can also use plain tests
describe file('/tmp') do
it { should be_directory }
end
# you add controls here
control 'tmp-1.0' do # A unique ID for this control
impact 0.7 # The criticality, if this control fails.
title 'Create /tmp directory' # A human-readable title
desc 'An optional description...'
describe file('/tmp') do # The actual test
it { should be_directory }
end
end
Tip for developing profiles
When creating new profiles use the existing example file as a template
This example shows two tests. Both tests check for the existence of the /tmp
directory. The second test provides additional information about the test. Let's break down each component.
control
(line 9) is followed by the control's name. Each control in a profile has a unique name.impact
(line 10) measures the relative importance of the test and must be a value between 0.0 and 1.0.title
(line 11) defines the control's purpose.desc
(line 12) provides a more complete description of what the control checks for.describe
(lines 13 β 15) defines the test. Here, the test checks for the existence of the/tmp
directory.
In Ruby, the do
and end
keywords define a block
. An InSpec control always contains at least one describe
block. However, a control can contain many describe
blocks.
More information on a block in Ruby
Understand a describe block's structure
As with many test frameworks, InSpec code resembles natural language. Here's the format of a describe block.
describe <entity> do
it { <expectation> }
end
An InSpec test has two main components: the subject to examine and the subject's expected state. Here, <entity>
is the subject you want to examine, for example, a package name, service, file, or network port. The <expectation>
specifies the desired result or expected state, for example, that a port should be open (or perhaps should not be open.)
Let's take a closer look at the describe
block in the example.
describe file('/tmp') do
it { should be_directory }
end
Because InSpec resembles human-readable language, you might read this test as "/tmp should be a directory." Let's break down each component.
file
file is an InSpec resource. If you're familiar with Chef, you know that a resource configures one part of the system. InSpec resources are similar. For example, the InSpec file resource tests for file attributes, including a file's owner, mode, and permissions. The example examines the /tmp directory.
it
The it
statement validates one of your resource's features. A describe
block contains one or more it
statements. it
enables you to test the resource itself. You'll also see its
, which describes some feature of the resource, such as its mode or owner. You'll see examples of both it
and its
shortly.
should
should
describes the expectation. should
asserts that the condition that follows should be true. Alternatively, should_not
asserts that the condition that follows should not be true. You'll see examples of both shortly.
be_directory
be_directory
is an example of a matcher. A matcher compares a resource's actual value to its expected value. InSpec provides several predefined matchers. The file
resource provides the be_directory
matcher.