Skip to content
SAF InSpec Profile DeveloperSAF InSpec Profile Developer
MITRE InSpec Profile Developer Course
Course
Resources
Installation
  • Course

    • Course Overview
      • Starting the Journey
        • Studying an InSpec Profile
          • Exploring the InSpec Shell
            • Writing InSpec Controls
              • Generating InSpec Results
                • Viewing and Analyzing Results
                  • InSpec Examples
                    • InSpec Examples
                      • RSpec Explicit Subject
                        • Looping Through Data
                          • The should vs. expect syntax
                            • Expect syntax and Password Hashes
                          • Profile Inheritance & Overlays
                            • From STIG to Profile

                            InSpec Examples

                            May 22, 2022About 2 min

                            On This Page
                            • InSpec Examples
                              • RSpec Explicit Subject
                              • Looping Through Data
                              • The should vs. expect syntax
                              • Expect syntax and Password Hashes

                            # InSpec Examples

                            # RSpec Explicit Subject

                            Here we have an InSpec test that lists out its current directory. Our original test code looks like this:

                            describe command('ls -al').stdout.strip do
                              it { should_not be_empty }
                            end
                            

                            If we would like to have a more detailed feedback to our user, we can override the standard title of our describe block with a specific message that describes the intent of the test and use the Explicit Subjectopen in new window to tell inspec what the "subject" is for the test, then, we could refactor the code like this:

                            describe "this is a detailed message" do
                              subject { command('ls -al').stdout.strip }
                              it{ should_not be_empty }
                            end
                            

                            # Looping Through Data

                            The file resource is perfect for looking at single files and thier properities, however, it does not look at groups of files. To do that we need to use multiple resources in concert. Let's use the command resource to run the find command, or it's equivalent for your target OS, and then use the file resource. Using multiple resources together is one of the key values InSpec provides, allowing you get get at just the data you need when you need it.

                            Avoid Large Sets or 'Check Everyone at the Door' Approaches

                            For IO intensive (full filesystem, or global scans) or large scale processes, try to be as specific as possible with your searches. Think about using 'negitive logic' vs 'positive logic' - "Find me all the items outside my target set" vs "Look at each item in the set and ensure it has these propertiies".

                            This 'find the outsiders' vs 'check everyone at the door' approach can really speed things along. Again, keep your data set as small as possible, don't inspect more then the requirements, well, requires.

                            command('find ~/* -type f -maxdepth 0 -xdev').stdout.split.each do |fname|
                              describe file(fname) do
                                its('owner') { should cmp 'ec2-user' }
                              end
                            end
                            

                            # The should vs. expect syntax

                            Users familiar with the rSpec testing framework may know that there are two ways to write test statements: should and expect. The RSpec community decided that expect is the preferred syntax.

                            InSpec recommends the should syntax as it tends to read more easily to those users who are not as technical, however there are times when the expect syntax will communicate much more clearly to the end-user.

                            InSpec will continue to support both methods of writing tests. Consider this file test:

                            describe file('/tmp/test.txt') do
                              it { should be_file }
                            end
                            

                            This can be re-written with expect syntax

                            describe file('/tmp/test.txt') do
                              it 'should be a file' do
                                expect(subject).to(be_file)
                              end
                            end
                            

                            The output of both of the above examples looks like this:

                            File /tmp/test.txt
                               ✔  should be a file
                            

                            In addition, you can make use of the subject keyword to further control your output if you choose:

                            describe 'test file' do
                              subject { file('/tmp/test.txt') }
                              it 'should be a file' do
                                expect(subject).to(be_file)
                              end
                            end
                            

                            … which will render the following output:

                            test file
                              ✔  should be a file
                            

                            Reference: https://docs.chef.io/inspec/profiles/open in new window

                            # Expect syntax and Password Hashes

                            Here we have an inspec test that checks if passwords are SHA512 hashes. As a quick thought exercise, can you think of how we can adjust the control below to support SHA512 or higher assuming where you are testing uses SHA1024 or even SHA2048?

                            As we said, when possible, and when there is a high change of a large set only having a few offending items, attempt to find only those items that could be outside our requirements, if there are none, wonderful, we met our requirement.

                            bad_users = inspec.shadow.where { password != "*" && password != "!" && password !~ /\$6\$/ }.users
                            
                            describe 'Password hashes in /etc/shadow' do
                              it 'should only contain SHA512 hashes' do
                                failure_message = "Users without SHA512 hashes: #{bad_users.join(', ')}"
                                expect(bad_users).to be_empty, failure_message
                              end
                            end
                            
                            Edit this pageopen in new window
                            Last update: 8/18/2022, 9:00:21 PM
                            Contributors: Aaron Lippold,Emily Rodriguez,wdower
                            Prev
                            Viewing and Analyzing Results
                            Next
                            Profile Inheritance & Overlays
                            Apache-2.0 | Copyright © 2022 - The MITRE Corporation
                            Copyright © 2022 Aaron Lippold