InSpec is an open-source testing framework that allows users to test and enforce security configurations and compliance for infrastructure code. It uses human-readable tests and resources to check configurations and generate reports. Users can write InSpec tests and profiles to test systems locally or remotely, address security issues, and integrate testing into development workflows using tools like Test Kitchen.
9. InSpec
• Human-readable
• Test security and compliance
• Create, share, and reuse profiles
• Extend for your applications and systems
• Plug into your existing workflows / build servers
• Fast feedback with Test Kitchen
10. Lifecycle
• When you get a mandate from security, how often is it checked?
• Single big scan, report mailed out with a “due date”?
• Yearly or twice-yearly massive scans with remediation firedrills?
11. SSH Requirement
• If your security team sends you a directive:
SSH supports two different protocol versions. The
original version, SSHv1, was subject to a number
of security issues. All systems must use SSHv2
instead to avoid these issues.
12. What To Do?
• Locate configuration file
• Locate correct setting
• Schedule a fix and restart
• Who fixes OS images?
• Do you need to test new settings?
13. Check that sshd_config
describe sshd_config do
impact 1.0
title 'SSH Version 2'
desc <<-EOF
SSH supports two different protocol versions. The original version, SSHv1, was subject to a
number of security issues. Please use SSHv2 instead to avoid these.
EOF
its('Protocol') { should cmp 2 }
end
14. Resources
• Resources examine common services, system files, and
configurations
See http://inspec.io/docs/reference/resources/ for the current list!
• Various Linux distros, plus Windows
• Check the characteristics of the resource (e.g., file size, owner)
• InSpec libraries are Matchers for testing and verifying
characteristics
15. • Resources include where the item is and how to look at it
• Included parsers do the work for you
• Similar to Ruby testing language rSpec, meant to be human
readable
16. its.... should...
• it { should exist }
• it { should be_installed }
• it { should be_enabled }
• its('max_log_file') { should cmp 6 }
• its('exit_status') { should eq 0 }
• its('gid') { should eq 0 }
17. SSH Configuration
describe sshd_config do
impact 1.0
title 'SSH Version 2'
desc <<-EOF
SSH supports two different protocol versions. The original version, SSHv1, was subject to a
number of security issues. Please use SSHv2 instead to avoid these.
EOF
its('Protocol') { should cmp 2 }
end
The Resource – built in
InSpec will find this in the fil
18. Run It
• InSpec is command line
Installs on your workstation as a ruby gem or as part of the ChefDK
• Can be run locally, test the machine it is executing on
• Or remotely
InSpec will log into the target and run the tests for you
• Also a REPL
https://www.inspec.io/docs/reference/shell/
20. Find It!
• http://inspec.io/
• Open Source, but cool stuff in the server
• Looks like other "spec" testing languages
• ChefDK or separate from downloads.chef.io
• It's already installed on your test host
$ inspec –version
3.0.12
21. Create a Basic Test – test.rb
• Let’s write a basic test to make sure /tmp is a directory
• It also should be owned by root
• And its mode should be 01777 – open to all (plus sticky bit!)
• Let’s check out the docs for the “file” resource for InSpec:w
22. File Resources in InSpec
• https://www.inspec.io/docs/reference/resources/file/
• We want:
Directory
Owner
Mode
describe file(‘path’) do
it { should MATCHER ‘value’ }
end
23. test.rb
describe file('/tmp') do
it { should exist }
it { should be_directory }
it { should be_owned_by 'root' }
its('mode') { should cmp '01777' }
end
describe file('/tmp/') do
it { should exist }
its('type') { should eq :directory }
it { should_not be_file }
its('owner') { should eq 'root' }
its('mode') { should cmp '01777' }
end
24. Test Any Target
inspec exec test.rb
inspec exec test.rb -i ~/.aws/cert.pem -t ssh://ec2-
user@192.168.1.2
inspec exec test.rb -t winrm://Admin@192.168.1.2 --password
super
inspec exec test.rb -t docker://3dda08e75838
25. Execute InSpec
[chef@host ~]$ inspec exec ./test.rb
Profile: tests from ./test.rb
Version: (not specified)
Target: local://
File /tmp
✔ should exist
✔ should be directory
✔ should be owned by "root"
✔ mode should cmp == "01777"
Test Summary: 4 successful, 0 failures, 0 skipped
27. Security Rule: set ssh login banner
• When logging into any machine your organization, display a notification:
"Welcome to MyCorp. This is a secure system and all activities are logged.
Authorized users only."
• The file /etc/ssh/sshd_banner
• We want it to exist and have the above content
28. $ vi banner.rb
describe file('/etc/ssh/sshd_banner') do
it { should exist }
its('content') { should match /Authorized users only/ }
end
29. $ sudo inspec exec banner.rb
Profile: tests from banner.rb (tests from banner.rb)
Version: (not specified)
Target: local://
File /etc/ssh/sshd_banner
× should exist
expected File /etc/ssh/sshd_banner to exist
× content should match /Authorized users only/
expected nil to match /Authorized users only/
Test Summary: 0 successful, 2 failures, 0 skipped
30. Test-driven Development
• We created the test first
• We know the feature we need does not exist on the machine
• Now we can create the sshd_banner file and re-run our test
• This helps us check our assumptions about the state of the system
• Create the banner file and run inspec again
31. $ sudo vi /etc/ssh/sshd_banner
Welcome to MyCorp.
This is a secure system and all activities are logged.
Authorized users only.
32. $ sudo inspec exec banner.rb
Profile: tests from banner.rb (tests from banner.rb)
Version: (not specified)
Target: local://
File /etc/ssh/sshd_banner
✔ should exist
✔ content should match /Authorized users only/
Test Summary: 2 successful, 0 failures, 0 skipped
33. $ vi banner.rb
...
describe file('/etc/ssh/sshd_config') do
its('content') { should match /^Banner /etc/ssh/sshd_banner/ }
end
34. $ sudo inspec exec banner.rb
Profile: tests from banner.rb (tests from banner.rb)
Version: (not specified)
Target: local://
File /etc/ssh/sshd_banner
✔ should exist
✔ content should match /Authorized users only/
File /etc/ssh/sshd_config
× content should match /$Banner /etc/ssh/sshd_banner/
expected "#t$OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp
$nn# This is the sshd server system...oncvsn#tX11Forwarding
non#tAllowTcpForwarding non#tPermitTTY non#tForceCommand cvs servern" to
match /$Banner /etc/ssh/sshd_banner/
35. $ sudo vi /etc/ssh/sshd_config
Find the line for the banner:
# no default banner path
#Banner none
Change to:
# add default banner path
Banner /etc/ssh/sshd_banner
36. $ sudo inspec exec banner.rb
Profile: tests from banner.rb (tests from banner.rb)
Version: (not specified)
Target: local://
File /etc/ssh/sshd_banner
✔ should exist
✔ content should match /Authorized users only/
File /etc/ssh/sshd_config
✔ content should match /^Banner /etc/ssh/sshd_banner/
Test Summary: 3 successful, 0 failures, 0 skipped
37. Profiles
• InSpec profiles allow you to package and share sets of InSpec
tests for your organization or for a specific application set
• Profiles are made up of controls
• Controls are made up of resources and tests, with priority and
metadata
Name your controls based on what they do or link them to a written doc
• Each profile can have multiple test files included and many
controls
38. Hardening with InSpec
• Centos 7 host
• os-hardening cookbook from https://supermarket.chef.io
• /dev-sec/linux-baseline InSpec profile from https://github.com/dev-
sec/linux-baseline
39. What’s in the linux-baseline Profile
control 'os-02' do
impact 1.0
title 'Check owner and permissions for /etc/shadow'
desc 'Check periodically the owner and permissions for /etc/shadow'
describe file('/etc/shadow') do
it { should exist }
it { should be_file }
it { should be_owned_by 'root' }
its('group') { should eq shadow_group }
it { should_not be_executable }
it { should be_writable.by('owner') }
...
40. Use the Profile
$ git clone https://github.com/dev-sec/linux-baseline
...
$ sudo inspec exec linux-baseline
Profile Summary: 27 successful controls, 26 control failures, 1
control skipped
Test Summary: 81 successful, 44 failures, 1 skipped
$
42. Use Chef to Repair the Findings
$ chef generate cookbook harden
43. $ vi harden/metadata.rb
name 'harden'
maintainer 'The Authors'
maintainer_email 'you@example.com'
license 'All Rights Reserved'
description 'Installs/Configures harden'
...
...
depends 'os-hardening'
44. Create a Cookbooks Package
$ cd harden
$ berks install
$ berks package
$ cd ..
$ tar –xzvf harden/cookbooks-VERSION.tar.gz
• This process will create a collection of Chef cookbooks to fix the issues that
caused InSpec to fail
• We won't need to connect to a Chef server for this method, all the
cookbooks will be downloaded locally
45. Run chef-client to remediate failed tests
$ sudo chef-client -r "recipe[os-hardening]" --local-mode
...
Chef Client finished, 141/206 resources updated in 08 seconds
• We're ignoring our harden cookbook for the moment, relying only on the os-
hardening cookbook that it downloaded. We could also change the recipes
in the harden cookbook to execute os-hardening from there. That's more
chef than we'll get into here.
46. Rerun the Tests
$ sudo inspec exec linux-baseline/
...
Profile Summary: 52 successful controls, 1 control failure, 1
control skipped
Test Summary: 124 successful, 1 failure, 1 skipped
47. Auditd
× package-08: Install auditd (1 failed)
✔ System Package audit should be installed
✔ Audit Daemon Config log_file should cmp == "/var/log/audit/audit.log"
✔ Audit Daemon Config log_format should cmp == "raw"
✔ Audit Daemon Config flush should match /^INCREMENTAL|INCREMENTAL_ASYNC$/
× Audit Daemon Config max_log_file_action should cmp == "keep_logs"
expected: "keep_logs"
got: ROTATE
(compared using `cmp` matcher)
48. What’s Still Failing?
• Find the controls that aren’t passing
• Decide if you want to fix them or forget them
• We'll build a new profile to wrap around linux-baseline
And exclude the failing test
49.
50. Building New Profiles
$ inspec init profile my_hardening
Create new profile at /home/chef/my_hardening
* Create file README.md
* Create directory controls
* Create file controls/example.rb
* Create file inspec.yml
* Create directory libraries
This is a new InSpec profile, vs the new Chef cookbook we created earlier.
51. Including Profiles
$ vi my_hardening/inspec.yml
name: my_hardening
title: InSpec Profile
...
version: 0.1.0
depends:
- name: linux-baseline
path: ../linux-baseline
52. Profile Dependencies
• InSpec will find or retrieve the included profile
• You can choose to use all of the profile or pick a few controls
• You can also exclude controls that don't meet your needs
• Create a new control file to manage the other profile's controls
53. Skipping Individual Controls
$ vi my_hardening/controls/my.rb
include_controls 'linux-baseline' do
skip_control ‘package-08'
end
We want to run all of the controls from linux-baseline except package-08
• You can also remove the file my_hardening/controls/example.rb if you want
to
54. Rerun the InSpec Profile
$ sudo inspec exec my_hardening/
...
Profile Summary: 53 successful controls, 0 control failures, 1
control skipped
Test Summary: 115 successful, 0 failures, 1 skipped
55. Additional Features
• Use InSpec to test resources in the Cloud – Azure, AWS, GCP
describe aws_s3_bucket('test_bucket') do
it { should_not be_public }
end
• Industry-standard profiles such as CIS available via commercial solutions
56. Test Kitchen
• InSpec also runs as a test suite in Test Kitchen
• Test Kitchen is a tool for your team to create fast-feedback loops for
development
• Add InSpec tests to TK so that any change can also be certified with the
security profile before it is pushed to source code repository
• More info at http://kitchen.ci/
57. InSpec and Chef's Automate
• InSpec profiles are a component of Chef's Automate server, providing a
GUI and metrics collection about compliance across your estate
• Additional industry-standard profiles are also available commercially via
Automate
Compliance requirements are often set out in flat documents. Sometimes PDFs, sometimes other formats, but they have a tendency to be a huge list of characteristics and checkboxes to be investigated and potentially remediated. Security tools may be somewhat more flexible, encoded into a set of shell scripts that check and verify the systems after they are built. But what if it was easy to build these checks into the workflow while the systems are being built and applications installed.
For the purposes of compliance, we actually wanted a common language, in code, that would allow all audiences – compliance, security, and devops – to collaborate on. And this code will then act on systems.
This is whyInSpec was developed.
For bits like the ssh configuration that are considered more infrastructure than application, these practices are common, changes are periodically rolled into the source images for new hosts (or containers) and the old configurations are eventually purged from production. It’s a herd-immunity approach.
But what happens if the thing to be tested is affected by a continuously developed application? Like run time configurations for java, or your databases. Can you count on every team to always know all of the requirements?
Plug InSpec into whatever command set you are already using