Resources & matchers
The building blocks of controls.
Resources are the vocabulary of InSpec, and it ships dozens: file, directory, package, service, port, user, group, sshd_config, and format-aware ones like json, yaml, ini, csv, plus command (run any command and assert on its output/exit). Each resource exposes properties and matchers suited to it. Fluency is knowing which resource answers your question — check a config value with the right parser resource rather than grepping a file, for accuracy.
describe file('/etc/passwd') doit { should exist }its('mode') { should cmp '0644' }it { should be_owned_by 'root' }enddescribe service('nginx') doit { should be_installed }it { should be_enabled }it { should be_running }enddescribe json('/etc/app/config.json') doits(['security','tls']) { should eq true }end
Matchers and cmp
Matchers express the assertion: should/should_not, be_* (be_running, be_listening), eq/match/include, and the InSpec-specific cmp, which is a lenient comparison that handles the string-vs-number, case, and octal-mode mismatches that plague config checks (cmp ‘0644’ matches whether the mode is a string or an integer). Prefer cmp for config values, use match for regex, and reach for the command resource only when no purpose-built resource exists.
# only when no dedicated resource fits — assert on real outputdescribe command('sysctl net.ipv4.ip_forward') doits('stdout') { should match /= 0/ }its('exit_status') { should eq 0 }end