6. Explore InSpec Resources
Before we dive into the course we want to take a look into what a resource is.
When writing InSpec code, many resources are available to you.
- You can explore the InSpec resources to see which resources are available.
- You can examine the source code to see what's available. For example, you can see how
file
and other InSpec resources are implemented.
There's also Resource DSL, which gives a brief overview of how to write your own resource.
6.1. Resource Overview
Resources may be added to profiles in the libraries folder:
$ tree examples/profile
examples/profile
...
├── libraries
│ └── gordon_config.rb
6.2. Resource Structure
The smallest possible resource takes this form:
class Tiny < Inspec.resource(1)
name 'tiny'
end
Resources are written as a regular Ruby class which inherits from Inspec.resource. The number (1) specifies the version this resource plugin targets. As Chef InSpec evolves, this interface may change and may require a higher version.
The following attributes can be configured:
- name - Identifier of the resource (required)
- desc - Description of the resource (optional)
- example - Example usage of the resource (optional)
- supports - (Chef InSpec 2.0+) Platform restrictions of the resource (optional)
The following methods are available to the resource:
- inspec - Contains a registry of all other resources to interact with the operating system or target in general.
- skip_resource - A resource may call this method to indicate that requirements aren’t met. All tests that use this resource will be marked as skipped.
The following example shows a full resource using attributes and methods to provide simple access to a configuration file:
class GordonConfig < Inspec.resource(1)
name 'gordon_config'
# Restrict to only run on the below platforms (if none were given, all OS's supported)
supports platform_family: 'fedora'
supports platform: 'centos', release: '6.9'
# Supports `*` for wildcard matcher in the release
supports platform: 'centos', release: '7.*'
desc '
Resource description ...
'
example '
describe gordon_config do
its("signal") { should eq "on" }
end
'
# Load the configuration file on initialization
def initialize(path = nil)
@path = path || '/etc/gordon.conf'
@params = SimpleConfig.new( read_content )
end
# Expose all parameters of the configuration file.
def method_missing(name)
@params[name]
end
private
def read_content
f = inspec.file(@path)
# Test if the path exist and that it's a file
if f.file?
# Retrieve the file's contents
f.content
else
# If the file doesn't exist, skip all tests that use gordon_config
raise Inspec::Exceptions::ResourceSkipped, "Can't read config at #{@path}"
end
end
end
Let's break down each component.
6.2.1. class
The class is where the ruby file is defined.
6.2.2. name
The name is how we will call upon this resource within our controls, in the example above that would be gordon_config
.
6.2.3. supports
Supports are used to define/restrict the Ruby resource to work in specific ways, as shown in the example above that is used to restrict our class to specific platforms.
6.2.4. desc & examples
desc is used as a simple in code description of the purpose of this resource while the example is to show how the resource can be used in a control.
6.2.5. initialize method
The initialize method is necessary because in inspec controls when we pass a parameter the Ruby class for the resource must have an initialize method to be defined to accept that paraemeter.
6.2.6. functionality methods
These are the methods that perform the actions you require the resource to perform.