Intro and 1.0 release
Alex Pop – Software Engineer @ Chef Software
https://uk.linkedin.com/in/al3xpop
Agenda
• Why infrastructure tests as code
• What is InSpec and how it works
• Core and custom resources
• What's new in InSpec 1.0 (released Sept 26, 2016)
• Documentation and installation
• Integrations
• Demo
• Chef Community Summit
Why infrastructure tests as code
• Regression and Integration testing
• Security and compliance testing
• Tests to run during incidents
• Checklist tests before upgrade / code release / etc
• Frameworks (InSpec, ServerSpec, Testinfra, Pester,
Bats, etc)
What is InSpec?
• Open-source framework and rule language to specify
compliance, security and policy for testing any node in your
environment.
• Includes a collection of resources to write rules quickly and
easily
• Profiles and custom resources provided by the community
What is InSpec and how it works
chef-client inspec
Open Source https://github.com/chef/chef https://github.com/chef/inspec
First Commit March 2008 April 2015
Language Ruby DSL Ruby DSL
Code
Execution Local Local & Remote (SSH, WinRM, Docker)
Artifacts Cookbooks & Recipes & Resources Profiles & Controls & Resources
Share Artifacts Chef Supermarket, Github, Bitbucket, etc Chef Supermarket, Github, Bitbucket, etc
service 'iptables' do
action [ :enable, :start ]
end
describe service('iptables') do
it { should be_enabled }
it { should be_running }
end
InSpec's execution overview
train gem
Target:
• Local (shell out)
• SSH (remote commands)
• WinRM (remote commands)
• Docker (exec, remote
commands)
auth & coms
InSpec's execution example
train gem
describe file('/etc/passwd') do
it { should exist }
it { should be_file }
its('mode') { should cmp '0644' }
its('owner') { should eq 'root' }
its('group') { should eq 'root' }
its('size') { should be > 100 }
end
Commands executed on target:
Basic OS detection(like Ohai):
uname
test -f /etc/os-release && cat /etc/os-release
test -f /etc/redhat-release && cat /etc/redhat-release
Resource specific commands:
test -e /etc/passwd
stat -L /etc/passwd
$ inspec exec /tmp/passwd.rb
$ inspec exec /tmp/passwd.rb -t docker://3dda08e75838
$ inspec exec /tmp/passwd.rb -t winrm://John@10.0.0.4 --password xyz
$ inspec exec /tmp/passwd.rb -t ssh://john@10.0.0.5 -i ~/john.pem
/tmp/passwd.rb content:
InSpec's controls examples
control 'windows-rdp-101' do
impact 1.0
title 'Strong Encryption for Windows Remote Desktop Required'
describe registry_key('HKLMSOFTWAREPoliciesMicrosoftWindows NTTerminal Services') do
it { should exist }
its('MinEncryptionLevel') { should eq 3 }
end
end
control 'sshd-11' do
impact 0.6
title 'Server: Set protocol version to SSHv2'
desc "Set the SSH protocol version to 2.
Don't use legacy insecure SSHv1 connections anymore."
tag 'ssh', 'sshd', 'openssh-server'
tag cce: 'CCE-27072-8'
tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening'
ref 'NSA-RH6-STIG-3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat'
describe sshd_config do
its('Protocol') { should eq '2' }
end
end
60+ resources: github.com / chef / inspec / lib / resources
apache, apache_conf, apt, audit_policy, auditd_conf,
auditd_rules, bash, bond, bridge, command, csv, directory,
etc_group, file, gem, groups, grub_conf, host, iis_site,
inetd_conf, ini, interface, iptables, json, kernel_module,
kernel_parameter, limits_conf, login_def, mount,
mssql_session, mysql, mysql_conf, mysql_session, npm,
ntp_conf, oneget, os, os_env, package, parse_config,
passwd, pip, port, postgres, postgres_conf, postgres_session,
powershell, processes, registry_key, security_policy,
service, shadow, ssh_conf, ssl, sys_info, users, vbscript,
windows_feature, wmi, xinetd, yaml, yum
Community profiles and custom resources
$ inspec supermarket profiles
== Available profiles:
* dev-sec/cis-docker-benchmark
* dev-sec/nginx-hardening
...
$ inspec supermarket info dev-sec/cis-docker-benchmark
name: cis-docker-benchmark
owner: dev-sec
url: https://github.com/dev-sec/cis-docker-benchmark
description: This InSpec compliance profile implements the CIS Docker 1.11.0
Benchmark in an automated way to provide security best-practice tests around
Docker daemon and containers in a production environment.
https://supermarket.chef.io/tools?type=compliance_profile
InSpec 1.0
• Integration with Chef Automate
• Dependency management(overlay profiles and custom resource
packs)
• Performance and Auth improvements for Windows, including Nano
• Profile Attributes
• Ability to write and test controls in InSpec shell
• Lots of bug fixes and improvements for the core resources
• Supported by docs and demo at http://inspec.io
Install and documentation
• Ruby gem (Included in Chef Development Kit)
• msi / dmg / rpm / deb package @
downloads.chef.io/inspec
• http://inspec.io/docs
• https://github.com/chef/inspec / docs
• inspec> help resource
Integrations
Compliance as Code (if it hurts...)
Demo time!
2-
inspec> os.params
{:name=>"centos", :family=>"redhat", :release=>"6.6", :arch=>"x86_64"}
inspec> help file
Name: file
Description:
Use the file InSpec audit resource to test all system file types,...SNIP...
Example:
describe file('path') do
it { should exist }
it { should be_file }
its('mode') { should cmp '0644' }
end
Demo: Use the inspec shell on a remote target
$ inspec shell -t ssh://root@10.0.0.5 -i ~/mykey.pem
2-
inspec> file('/etc/hosts').exist?
=> true
inspec> file('/etc/hosts').size
=> 183
inspec> describe file('/etc/hosts') do
inspec> its('size') { should be < 100 }
inspec> end
File /etc/hosts
✖ size should be < 100
expected: < 100
got: 183
inspec> ls file('/etc/hosts') # see all available methods for the file resource
basename directory? exist? group link_path mount_options path
sgid source_path type sha256sum sticky uid md5sum size mode
Demo: Use the file resource and test it in the shell
$ inspec shell -t ssh://root@10.0.0.5 -i ~/mykey.pem
2-
├── README.md
├── inspec.yml
├── controls
│ └── example.rb
└── libraries
Demo: Profile structure
$ inspec init profile mycerts
$ tree ~/tmp/mycerts
2-
name: mycerts
title: InSpec Profile
maintainer: The Authors
copyright: The Authors
copyright_email: you@example.com
license: All Rights Reserved
summary: An InSpec Compliance Profile
version: 0.1.0
depends: # << added in order to use a resource defined in this profile
- name: ssl-certificate-profile
git: https://github.com/alexpop/ssl-certificate-profile
version: '< 1.0.0'
Demo: Create and inherit ssl-certificate-profile
$ cat inspec.yml
2-
# allows us to inherit all controls, but skip a few if needed
include_controls 'ssl-certificate-profile' do
skip_control 'CHECK expired.badssl.com'
# we can also override, controls, in this example changing the impact
control 'CHECK sha1-2016.badssl.com' do
impact 1.0
end
end
# allows us to cherry pick the controls we want from the dependent profile
require_controls 'ssl-certificate-profile' do
control 'CHECK github.com'
end
Demo: Wrap(overlay) the inherited profile
$ cat controls/example.rb
2-
# example on how to define a profile attribute
val_path = attribute('path', default: '/etc/cert', description: 'Example attr...')
# use the ssl_certificate custom resource from the dependent profile
describe ssl_certificate(host: 'github.io') do
it { should exist }
it { should be_trusted }
its('hash_algorithm') { should eq 'SHA256' }
its('expiration_days') { should be >= 30 }
its('key_size') { should be >= 2048 }
end
Demo: Use the resource from the dependent
profile$ cat controls/example.rb
2-
✔ CHECK github.com: Verify github.com`s SSL certificate
✔ ssl_certificate github.com:443 should exist
✔ ssl_certificate github.com:443 should be trusted
✔ ssl_certificate github.com:443 expiration_days should be >= 30
...SNIP...
Profile Summary: 1 successful, 0 failures, 0 skipped
$ inspec exec ~/tmp/mycerts --format json | jq
{
"version": "1.0.0",
"profiles": [
{
"name": "mycerts",
"title": "InSpec Profile",
"version": "0.1.0",
Demo: Execute the profile with cli and json formats
$ inspec exec ~/tmp/mycerts
2-
class SslCertificate < Inspec.resource(1)
name 'ssl_certificate'
desc 'The `ssl_certificate` allows to test ...SNIP..'
example 'describe ssl_certificate do ...SNIP...'
def initialize(opts = {})
# ... plain Ruby or other InSpec resources here like: inspec.file(path)
@cert = http.peer_cert
end
# Called by: its('signature_algorithm') { should eq 'something' }
def signature_algorithm
return @cert.signature_algorithm
end
def expiration_days
return ((@cert.not_after - Time.now) / 86_400).to_i
end
end
Demo: Dissect the ssl_certificate custom resource
$ cat ssl-certificate-profile/libraries/ssl_certificate.rb
2-
def signature_algorithm
require 'pry'
binding.pry # execution will stop here and give me a pry> shell
return @cert.signature_algorithm
end
def expiration_days
return ((@cert.not_after - Time.now) / 86_400).to_i
end
end
[1] pry> @cert.signature_algorithm
=> "sha256WithRSAEncryption"
[2] pry> ls @cert
OpenSSL::X509::Certificate#methods:
add_extension extensions= not_before public_key serial= subject
to_pem verify check_private_key inspect not_after not_before
Pry breakpoints (in profiles, resources, recipes etc)
$ inspec exec ~/tmp/mycerts
https://summit.chef.io/london
Presentations
Collaboration
Food & _ _ _ _
Q&A

Introduction to InSpec and 1.0 release update

  • 1.
    Intro and 1.0release Alex Pop – Software Engineer @ Chef Software https://uk.linkedin.com/in/al3xpop
  • 2.
    Agenda • Why infrastructuretests as code • What is InSpec and how it works • Core and custom resources • What's new in InSpec 1.0 (released Sept 26, 2016) • Documentation and installation • Integrations • Demo • Chef Community Summit
  • 3.
    Why infrastructure testsas code • Regression and Integration testing • Security and compliance testing • Tests to run during incidents • Checklist tests before upgrade / code release / etc • Frameworks (InSpec, ServerSpec, Testinfra, Pester, Bats, etc)
  • 4.
    What is InSpec? •Open-source framework and rule language to specify compliance, security and policy for testing any node in your environment. • Includes a collection of resources to write rules quickly and easily • Profiles and custom resources provided by the community
  • 5.
    What is InSpecand how it works chef-client inspec Open Source https://github.com/chef/chef https://github.com/chef/inspec First Commit March 2008 April 2015 Language Ruby DSL Ruby DSL Code Execution Local Local & Remote (SSH, WinRM, Docker) Artifacts Cookbooks & Recipes & Resources Profiles & Controls & Resources Share Artifacts Chef Supermarket, Github, Bitbucket, etc Chef Supermarket, Github, Bitbucket, etc service 'iptables' do action [ :enable, :start ] end describe service('iptables') do it { should be_enabled } it { should be_running } end
  • 6.
    InSpec's execution overview traingem Target: • Local (shell out) • SSH (remote commands) • WinRM (remote commands) • Docker (exec, remote commands) auth & coms
  • 7.
    InSpec's execution example traingem describe file('/etc/passwd') do it { should exist } it { should be_file } its('mode') { should cmp '0644' } its('owner') { should eq 'root' } its('group') { should eq 'root' } its('size') { should be > 100 } end Commands executed on target: Basic OS detection(like Ohai): uname test -f /etc/os-release && cat /etc/os-release test -f /etc/redhat-release && cat /etc/redhat-release Resource specific commands: test -e /etc/passwd stat -L /etc/passwd $ inspec exec /tmp/passwd.rb $ inspec exec /tmp/passwd.rb -t docker://3dda08e75838 $ inspec exec /tmp/passwd.rb -t winrm://John@10.0.0.4 --password xyz $ inspec exec /tmp/passwd.rb -t ssh://john@10.0.0.5 -i ~/john.pem /tmp/passwd.rb content:
  • 8.
    InSpec's controls examples control'windows-rdp-101' do impact 1.0 title 'Strong Encryption for Windows Remote Desktop Required' describe registry_key('HKLMSOFTWAREPoliciesMicrosoftWindows NTTerminal Services') do it { should exist } its('MinEncryptionLevel') { should eq 3 } end end control 'sshd-11' do impact 0.6 title 'Server: Set protocol version to SSHv2' desc "Set the SSH protocol version to 2. Don't use legacy insecure SSHv1 connections anymore." tag 'ssh', 'sshd', 'openssh-server' tag cce: 'CCE-27072-8' tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening' ref 'NSA-RH6-STIG-3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat' describe sshd_config do its('Protocol') { should eq '2' } end end
  • 9.
    60+ resources: github.com/ chef / inspec / lib / resources apache, apache_conf, apt, audit_policy, auditd_conf, auditd_rules, bash, bond, bridge, command, csv, directory, etc_group, file, gem, groups, grub_conf, host, iis_site, inetd_conf, ini, interface, iptables, json, kernel_module, kernel_parameter, limits_conf, login_def, mount, mssql_session, mysql, mysql_conf, mysql_session, npm, ntp_conf, oneget, os, os_env, package, parse_config, passwd, pip, port, postgres, postgres_conf, postgres_session, powershell, processes, registry_key, security_policy, service, shadow, ssh_conf, ssl, sys_info, users, vbscript, windows_feature, wmi, xinetd, yaml, yum
  • 10.
    Community profiles andcustom resources $ inspec supermarket profiles == Available profiles: * dev-sec/cis-docker-benchmark * dev-sec/nginx-hardening ... $ inspec supermarket info dev-sec/cis-docker-benchmark name: cis-docker-benchmark owner: dev-sec url: https://github.com/dev-sec/cis-docker-benchmark description: This InSpec compliance profile implements the CIS Docker 1.11.0 Benchmark in an automated way to provide security best-practice tests around Docker daemon and containers in a production environment. https://supermarket.chef.io/tools?type=compliance_profile
  • 11.
    InSpec 1.0 • Integrationwith Chef Automate • Dependency management(overlay profiles and custom resource packs) • Performance and Auth improvements for Windows, including Nano • Profile Attributes • Ability to write and test controls in InSpec shell • Lots of bug fixes and improvements for the core resources • Supported by docs and demo at http://inspec.io
  • 12.
    Install and documentation •Ruby gem (Included in Chef Development Kit) • msi / dmg / rpm / deb package @ downloads.chef.io/inspec • http://inspec.io/docs • https://github.com/chef/inspec / docs • inspec> help resource
  • 13.
  • 14.
    Compliance as Code(if it hurts...)
  • 16.
  • 17.
    2- inspec> os.params {:name=>"centos", :family=>"redhat",:release=>"6.6", :arch=>"x86_64"} inspec> help file Name: file Description: Use the file InSpec audit resource to test all system file types,...SNIP... Example: describe file('path') do it { should exist } it { should be_file } its('mode') { should cmp '0644' } end Demo: Use the inspec shell on a remote target $ inspec shell -t ssh://root@10.0.0.5 -i ~/mykey.pem
  • 18.
    2- inspec> file('/etc/hosts').exist? => true inspec>file('/etc/hosts').size => 183 inspec> describe file('/etc/hosts') do inspec> its('size') { should be < 100 } inspec> end File /etc/hosts ✖ size should be < 100 expected: < 100 got: 183 inspec> ls file('/etc/hosts') # see all available methods for the file resource basename directory? exist? group link_path mount_options path sgid source_path type sha256sum sticky uid md5sum size mode Demo: Use the file resource and test it in the shell $ inspec shell -t ssh://root@10.0.0.5 -i ~/mykey.pem
  • 19.
    2- ├── README.md ├── inspec.yml ├──controls │ └── example.rb └── libraries Demo: Profile structure $ inspec init profile mycerts $ tree ~/tmp/mycerts
  • 20.
    2- name: mycerts title: InSpecProfile maintainer: The Authors copyright: The Authors copyright_email: you@example.com license: All Rights Reserved summary: An InSpec Compliance Profile version: 0.1.0 depends: # << added in order to use a resource defined in this profile - name: ssl-certificate-profile git: https://github.com/alexpop/ssl-certificate-profile version: '< 1.0.0' Demo: Create and inherit ssl-certificate-profile $ cat inspec.yml
  • 21.
    2- # allows usto inherit all controls, but skip a few if needed include_controls 'ssl-certificate-profile' do skip_control 'CHECK expired.badssl.com' # we can also override, controls, in this example changing the impact control 'CHECK sha1-2016.badssl.com' do impact 1.0 end end # allows us to cherry pick the controls we want from the dependent profile require_controls 'ssl-certificate-profile' do control 'CHECK github.com' end Demo: Wrap(overlay) the inherited profile $ cat controls/example.rb
  • 22.
    2- # example onhow to define a profile attribute val_path = attribute('path', default: '/etc/cert', description: 'Example attr...') # use the ssl_certificate custom resource from the dependent profile describe ssl_certificate(host: 'github.io') do it { should exist } it { should be_trusted } its('hash_algorithm') { should eq 'SHA256' } its('expiration_days') { should be >= 30 } its('key_size') { should be >= 2048 } end Demo: Use the resource from the dependent profile$ cat controls/example.rb
  • 23.
    2- ✔ CHECK github.com:Verify github.com`s SSL certificate ✔ ssl_certificate github.com:443 should exist ✔ ssl_certificate github.com:443 should be trusted ✔ ssl_certificate github.com:443 expiration_days should be >= 30 ...SNIP... Profile Summary: 1 successful, 0 failures, 0 skipped $ inspec exec ~/tmp/mycerts --format json | jq { "version": "1.0.0", "profiles": [ { "name": "mycerts", "title": "InSpec Profile", "version": "0.1.0", Demo: Execute the profile with cli and json formats $ inspec exec ~/tmp/mycerts
  • 24.
    2- class SslCertificate <Inspec.resource(1) name 'ssl_certificate' desc 'The `ssl_certificate` allows to test ...SNIP..' example 'describe ssl_certificate do ...SNIP...' def initialize(opts = {}) # ... plain Ruby or other InSpec resources here like: inspec.file(path) @cert = http.peer_cert end # Called by: its('signature_algorithm') { should eq 'something' } def signature_algorithm return @cert.signature_algorithm end def expiration_days return ((@cert.not_after - Time.now) / 86_400).to_i end end Demo: Dissect the ssl_certificate custom resource $ cat ssl-certificate-profile/libraries/ssl_certificate.rb
  • 25.
    2- def signature_algorithm require 'pry' binding.pry# execution will stop here and give me a pry> shell return @cert.signature_algorithm end def expiration_days return ((@cert.not_after - Time.now) / 86_400).to_i end end [1] pry> @cert.signature_algorithm => "sha256WithRSAEncryption" [2] pry> ls @cert OpenSSL::X509::Certificate#methods: add_extension extensions= not_before public_key serial= subject to_pem verify check_private_key inspect not_after not_before Pry breakpoints (in profiles, resources, recipes etc) $ inspec exec ~/tmp/mycerts
  • 26.
  • 27.

Editor's Notes

  • #4 Use-cases I'm seeing in the DevOps space for running infrastructure tests as code
  • #6 Look at chef-client and inspec and see the similarities and differences between the two. DSL = Domain Specific Language
  • #7 The open-source train gem is used by InSpec to handle authentication and communication with the target node or container. It uses a number of supported transports like: ssh, winrm, docker Communication involves passing commands and retrieving STDOUT, STDERR and exit codes.
  • #8 This shows in more details the role the train gem is playing. After the authentication with the target node, it's running a few discovery commands to figure out a few things like: Operating System family and version, CPU architecture, etc. The discovery part gives the inspec resources the information needed to handle different platforms. In this example, the file resource requires two more commands(test and stat) and a bit of parsing to conclude the test.
  • #9 We have two more tests here, using the registry_key and sshd_config core resources. In these examples, the tests are grouped in controls that provide the ability to specify metadata. This is useful for reporting purposes or anyone reviewing the controls.
  • #10 A rough list of core resources shipped with InSpec 1.0. The most popular ones highlighted in bold
  • #11 Inspec has a subcommand to query compliance profiles shared on supermarket.chef.io
  • #14 * kitchen-inspec is a test-kitchen driver that can be used to run tests against local vms, cloud instances or containers. * Use Chef Compliance to scan your entire IT infrastructure and get easy to understand reports on compliance issues, security risks, and out of date software. It comes with a good number of industry standard CIS profiles for RedHat, Ubuntu, Windows, HP-UX, AIX, OSX, etc * Chef Automate gives you a full-stack continuous deployment pipeline, automated testing for compliance and security, and visibility into everything that's happening along the way. * The audit cookbook allows you to run Chef Compliance profiles as part of a Chef Client run.
  • #15 If it hurts, do it more often What you get is compliance expressed as code that can be tested, which is a powerful concept. The ability to test leads to fewer errors and instant feedback. This feedback loop reflects our level of compliance as early and quickly as possible, giving us velocity and consistency.
  • #16 Screenshot of Chef Automate showing the compliance status of a vanilla CentOS6 node after running the CIS CentOS6 Level 2 profile.
  • #18 The InSpec shell give you a nice environment to dev and test you code. It increases productivity by having a very quick feedback loop.
  • #19 Try out the file resource
  • #21 We edit inspec.yml, the metadata file of the profile, in order to specify a dependency for the ssl-certificate-profile in github This allows us to inherit controls from the dependent profile or use any of it's custom resources
  • #22 Two examples of how we can now benefit from controls defined in the dependent profile(ssl-certificate-profile)
  • #23 Starts by showing how to define a profile attribute Then, we use the ssl_certificate resource defined in our dependency, ssl-certificate-profile
  • #24 Showing the execution output when: * we don't specify the formatter(defaults to cli) * when we specify json format. Other formats: json-min, progress
  • #25 We are having a quick look into the ssl_certificate custom resource used in the previous slides. First, we define a few metadata properties like name, desc and example. We then have the initialize method that called when a profile uses the resource, for example: describe ssl_certificate(host: 'bbc.co.uk') do ... end Then, we define a method for each property this custom resource supports. In this example: signature_algorithm and expiration_days
  • #26 Tech tip: Because inspec is Ruby DSL, you can put pry breakpoints in resources and profiles to stop the execution and try things out in the shell. Really useful for dev and troubleshooting
  • #27 _ _ _ _ Hugs :)
  • #28 Thanks for listening and happy coding!