5.4 KiB
layout | title | category | tags | summary |
---|---|---|---|---|
post | Writing InSpec Wrapper Profiles | chef_inspec | [inspec cis security] | No one is fully compliant, here's how you write a profile fits your environment |
What is a wrapper profile?
Chef InSpec groups controls and tests in a standalone artifact known as a profile. These profiles can include other profiles and bundle/vendor those profiles to be executed at runtime.
A wrapper profile is just that, a profile that includes controls/resources from another profile.
Why would I use a wrapper profile?
In addition to adding custom resources, wrapping profiles allows you to customize the exact set of controls that are executed during runtime. Additionally, it is possible to modify the included controls to reduce the severity/impact or redefine/modify tests. Most commonly, wrapper profiles are used to implement a strict compliance posture in a way that allows you to audit/track only the items you care about.
For example, it is very difficult to comply entirely with DISA/NIST/CIS standards. By using wrapper profiles you can take advantage of the majority of the security benefits being offered without cluttering up your reports with items that are not relevant to you or your organization.
Creating a Wrapper Profile
Creating a wrapper profile is a simple as adding a dependency to your
profile's inspec.yml
file and using include_controls
or require_controls
.
Defining dependencies
When defining dependencies two things are needed:
- A name, this is used when referencing a dependent profile in your profile
- A source to fetch the dependent profile
As of the time of this writing, sources can be any of the following:
- A local path on disk (
path:
) - A URL to a tar/zip (
url:
) - A GitHub repository (
github:
) - A Chef Automate server (
compliance:
)
For more information on how to use each of these see:
https://www.inspec.io/docs/reference/profiles/#defining-the-dependencies
Including/Requiring controls
Controls are included from dependant profiles by using either
include_controls
or require_controls
. The main difference between these two
is that include_controls
includes all controls from the dependent profile
whereas require_controls
only includes the controls specified within the
do
/end
block.
include_controls
Using include_controls
will include all controls from the referenced profile.
Certain controls can be excluded from this inclusion by using: skip_control
.
For example, let's say you wanted to include all controls from some-profile
but skip the some-strict-control
(defined via control 'some-strict-control
).
Do the following:
# `some_profile` corresponds to `name:` in the `inspec.yml` `depends:` section
include_controls 'some-profile' do
skip_control 'some-strict-control'
end
require_controls
Using require_conrols
will only execute the controls you specify from the
dependant profile.
For example, let's say you want to include some specific controls from a dependent profile, but not include all the controls from that profile.
Do the following:
# `some_profile` corresponds to `name:` in the `inspec.yml` `depends:` section
require_controls 'some-profile' do
control 'some-strict-control'
end
Modifying Included Controls
Whether you are using include_controls
or require_controls
, the included
controls can be modified.
For example, let's say you want to include all the controls from some-profile
but the telnet
control from the included profile only specifies that the
package telnetd
is not installed and does not account for the fact that
CentOS's package is called telnet-server
.
Do the following:
# `some_profile` corresponds to `name:` in the `inspec.yml` `depends:` section
include_control 'some-profile' do
control 'telnet' do
telnet_server_packages = %w(telnetd telnet-server)
telnet_server_packages do |telnet_package|
package telnet_package do
it { should_not be_installed }
end
end
end
end
This will overwrite the tests in the some-profile
control named telnet
but
will not modify things such as impact
, title
, or desc
.
Example: Wrapping a CIS Profile
Chef Automate includes several built in Chef InSpec profiles for a variety of platforms.
The example will:
- Include all controls from the
cis-centos7-level2
profile - Modify the impact of the SSHD control to be informational
- Justification: You would like to have a banner but it needn't be a 'critical' failure
- Modify the HTTP server control to not execute/fail if a web server is running
- Justification: You want to run this profile, but don't want web servers to fail
First, add the following to your profile's inspec.yml
:
depends:
- name: 'cis-centos7-level2'
compliance: 'secteam/cis-centos7-level2'
Then add the following to one of your controls:
include_controls 'cis-centos7-level2' do
control 'xccdf_org.cisecurity.benchmarks_rule_6.2.14_Set_SSH_Banner' do
impact 0.0
end
control 'xccdf_org.cisecurity.benchmarks_rule_3.11_Remove_HTTP_Server' do
# TODO: Remove me when/if InSpec add support for `not_if`
only_if('This server is a webserver') do
!service('httpd').running? || !service('apache2').running?
end
end
end
NOTE: Message after the
only_if
will only show if the control is skipped