# Profile Inheritance and Overlays

In addition to its own controls, an InSpec profile can bring in the controls from another InSpec profile. Additionally, when inheriting the controls of another profile, a profile can skip or even modify those included controls.

When a profile includes controls from another profile, it is usually referred to as a “meta profile” or a “profile overlay.” Those of us with Chef background sometimes call it a “wrapper profile”.

::: info Further information on inheritance You can find out more about inhertiance here https://www.inspec.io/docs/reference/profiles/#sts=Profile%20Dependencies (opens new window) :::

# Defining the Profile Dependency

Before a profile (e.g. Profile A) can use controls from another profile (e.g. Profile B), Profile B needs to be included in Profile A's inspec.yml file in the depends section. Each profile that Profile A depends on should list its name and location. For example:

depends:
 - name: linux-baseline
   url: https://github.com/dev-sec/linux-baseline/archive/master.tar.gz
 - name: ssh-baseline
   url: https://github.com/dev-sec/ssh-baseline/archive/master.tar.gz
1
2
3
4
5

Once defined in the inspec.yml file, controls from the included profiles can be used!

# Including All Controls from a Profile

With the include_controls command in a profile, all controls from the named profile will be executed every time the including profile is executed. Below you can see an example of a profile and overlay.

# my_nginx profile
control 'nginx-version' do
  impact 1.0
  title 'NGINX version'
  desc 'The required version of NGINX should be installed.'
end

control 'nginx-modules' do
  impact 1.0
  title 'NGINX modules'
  desc 'The required NGINX modules should be installed.'
end

control 'nginx-conf' do
  impact 1.0
  title 'NGINX configuration'
  desc 'The NGINX config file should owned by root, be writable only by owner, and not writeable or and readable by others.'
end

include_controls `my_nginx_overlay`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# my_nginx_overlay
control `first-overlay-control`
control `second-overlay-control`
1
2
3

In the example above, every time my_nginx profile is executed, all the controls from my_nginx_overlay are also executed. Therefore, the following controls would be executed:

  • nginx-version
  • nginx-modules
  • nginx-conf
  • first-overlay-control
  • second-overlay-control

# Skipping a Control From a Profile

What if one of the controls from the included profile does not apply to your environment? Luckily, it is not necessary to maintain a slightly-modified copy of the included profile just to delete a control. The skip_control command tells InSpec to not run a particular control.

# my_nginx profile
control 'nginx-version' do
  impact 1.0
  title 'NGINX version'
  desc 'The required version of NGINX should be installed.'
end

control 'nginx-modules' do
  impact 1.0
  title 'NGINX modules'
  desc 'The required NGINX modules should be installed.'
end

control 'nginx-conf' do
  impact 1.0
  title 'NGINX configuration'
  desc 'The NGINX config file should owned by root, be writable only by owner, and not writeable or and readable by others.'
end

include_controls `my_nginx_overlay` do
  skip_control `second-overlay-control`
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# my_nginx_overlay
control `first-overlay-control`
control `second-overlay-control`
1
2
3

In the above example, all controls from my_nginx profile and my_nginx_overlay profile will be executed every time my-app-profile is executed except for control second-overlay-control from the my_nginx_overlay profile.

# Modifying a Control

Let’s say a particular control from an included profile should still run, but the impact isn’t appropriate? Perhaps the test should still run, but if it fails it should be treated as low severity instead of high severity?

When a control is included, it can also be modified!

# my_nginx profile
control 'nginx-version' do
  impact 1.0
  title 'NGINX version'
  desc 'The required version of NGINX should be installed.'
end

control 'nginx-modules' do
  impact 1.0
  title 'NGINX modules'
  desc 'The required NGINX modules should be installed.'
end

control 'nginx-conf' do
  impact 1.0
  title 'NGINX configuration'
  desc 'The NGINX config file should owned by root, be writable only by owner, and not writeable or and readable by others.'
end

include_controls `my_nginx_overlay` do
  control `second-overlay-control` do
    impact 0.5
  end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# my_nginx_overlay
control `first-overlay-control` do
  impact 1.0
end
control `second-overlay-control` do
  impact 1.0
end
1
2
3
4
5
6
7

In the above example, all controls from my_nginx profile are executed along with all the controls from the including profile, my_nginx_overlay. However, should control second-overlay-control fail, it will be raised with an impact of 0.5 instead of the originally-intended impact of 1.0.

# Selectively Including Controls From a Profile

If there are only a handful of controls that should be executed from an included profile, it’s not necessary to skip all the unneeded controls, or worse, copy/paste those controls bit-for-bit into your profile. Instead, use the require_controls command.

# my_nginx profile  
control 'nginx-version' do
  impact 1.0
  title 'NGINX version'
  desc 'The required version of NGINX should be installed.'
end

control 'nginx-modules' do
  impact 1.0
  title 'NGINX modules'
  desc 'The required NGINX modules should be installed.'
end

control 'nginx-conf' do
  impact 1.0
  title 'NGINX configuration'
  desc 'The NGINX config file should owned by root, be writable only by owner, and not writeable or and readable by others.'
end

require_controls `my_nginx_overlay` do
  control `first-overlay-control`
  control `third-overlay-control`
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# my_nginx_overlay
control `first-overlay-control`
control `second-overlay-control`
control `third-overlay-control`
control `fourth-overlay-control`
control `fifth-overlay-control`
1
2
3
4
5
6

Whenever my_nginx is executed, in addition to its own controls, it will run only the controls specified in the require_controls block. In the case, the following controls would be executed:

  • nginx-version
  • nginx-modules
  • nginx-conf
  • first-overlay-control
  • third-overlay-control

Controls second-overlay-control, fourth-overlay-control, and fifth-overlay-control would not be run, just as if they were manually skipped. This method of including specific controls ensures only the controls specified are executed; if new controls are added to a later version of my_nginx_overlay, they would not be run.

And, just the way its possible to modify controls when using include_controls, controls can be modified as well.

# my_nginx profile  
control 'nginx-version' do
  impact 1.0
  title 'NGINX version'
  desc 'The required version of NGINX should be installed.'
end

control 'nginx-modules' do
  impact 1.0
  title 'NGINX modules'
  desc 'The required NGINX modules should be installed.'
end

control 'nginx-conf' do
  impact 1.0
  title 'NGINX configuration'
  desc 'The NGINX config file should owned by root, be writable only by owner, and not writeable or and readable by others.'
end

require_controls `my_nginx_overlay` do
  control `first-overlay-control` do
    impact 0.5
  end
  control `third-overlay-control`
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# my_nginx_overlay
control `first-overlay-control` do
  impact 1.0
end

control `second-overlay-control`
control `third-overlay-control`
control `fourth-overlay-control`
control `fifth-overlay-control`
1
2
3
4
5
6
7
8
9

As with the prior example, only first-overlay-control and third-overlay-control are executed, but if first-overlay-control fails, it will report with an impact of 0.5 instead of the originally-intended 1.0 impact.

# Additional Examples

# Exercise

Create your own overlay profile for nginx and use 5 controls that you would want to modify.