2. Review the Fundamentals
InSpec Content Review
In the beginner class, we explained the structure of InSpec profiles and controls, how to run them, and how to understand their results. Let's do a brief review of that fundamental content and then practice those basic skills again.
InSpec Profile Structure
Remember that a profile
is a set of automated tests that usually relates directly back to some upstream security guidance document.
Profiles have two (2) required elements:
- An
inspec.yml
file - A
controls
directory
and optional elements such as:
- A
libraries
directory - A
files
directory - An
inputs.yml
file - A
README.md
file
InSpec can create the profile structure for you using the following command:
inspec init profile my_inspec_profile
This will give you the required files along with some optional files.
$ tree my_inspec_profile
my_inspec_profile
βββ README.md
βββ controls
β βββ example.rb
βββ inspec.yml
Default File Structures
Control File Structure
Let's take a look at the default Ruby file in the controls
directory.
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
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.
Describe Block 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
Resources And Matchers
InSpec uses resources like the file
resource to aid in control development. These resources can often be used as the < entity >
in the describe block. Find a list of resources in the InSpec documentation
InSpec uses matchers like the cmp
or eq
to aid in control development. These matchers can often be used as the < expectation >
in the describe block where the expectation is checking a requirement of that entity. Find a list of matchers in the InSpec documentation
inspec.yml File Structure
Let's take a look at the default inspec.yml
.
name: my_inspec_profile
title: InSpec Profile
maintainer: The Authors
copyright: The Authors
copyright_email: you@example.com
license: Apache-2.0
summary: An InSpec Compliance Profile
version: 0.1.0
supports:
platform: os
# Optional sections
depends:
- name: < name of the profile from which you can include controls >
path: < relative path to that profile >
gem_dependencies:
- name: < name of the gem >
version: < version of the gem >
inputs:
- name: < name of the input >
desc: < description of the input >
type: < data type of the input (String, Array, Numeric, Hash) >
value: < default value for the input >
This example shows default metadata of the InSpec profile along with the optional sections. Find more information about inputs and overlays in the beginner class.
Tips
version
(line 8) is the version of that inspec profile. The best practice is for the version to be bumped after making changes to the profile to pull the latest updates.
Difference between 'inspec.yml' and 'inputs.yml'
inspec.yml | inputs.yml |
---|---|
Required | Optional |
Should not be renamed | Can be renamed |
Needs to be at the root of the profile | Can be anywhere |
Automatically used during executioninspec exec profile1 | Needs to be passed in during executioninspec exec profile1 --input-file <path> |
Declare variables used within the profile, can provide default values | Override default input values (as needed) with parameters appropriate for the local environments |
Defined by the author of the profile | Defined by the user of the profile |
- name: superusers
desc: 'List of users with admin privileges'
type: Array
value:
- 'admin'
- 'root'
superusers:
- 'codespaces'
- 'kali'