# 3. 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
2
3
4
5
6
# 3.1. 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
2
3
4
5
6
7
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 (opens new window). You won't work with resource extensions in this module.
# 3.2. 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 12) is followed by the control's name. Each control in a profile has a unique name.impact
(line 13) measures the relative importance of the test and must be a value between 0.0 and 1.0.title
(line 14) defines the control's purpose.desc
(line 15) provides a more complete description of what the control checks for.describe
(lines 16 — 18) 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
# 3.3. 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
2
3
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>
part 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
2
3
Because InSpec resembles human-readable language, you might read this test as "/tmp should be a directory." Let's break down each component.
# 3.3.1. file
file (opens new window) is an InSpec resource (opens new window). 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.
# 3.3.2. 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.
# 3.3.3. 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.
# 3.3.4. be_directory
be_directory
is an example of a matcher (opens new window). 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.