I want to use guards in my inspec controls so they only run on nodes with the appropriate tags.
In the recipe DSL, we can use tagged?('my_tag')
. This method doesn't seem to be available in InSpec.
Is there a similar way to check for node tags during an InSpec run?
The alternative of course is to use knife search 'tags:my_tag' -i
and then run the appropriate controls on the nodes returned. I am just looking for a way to do it all at once.
I see there was a feature request https://github.com/inspec/inspec/issues/1677 but still looks open.
What i've come up with, to do many nodes with different tags all at once, is to use the --controls=/regex/
parameter. I gather all the nodes, get the tags for each one, and only run the controls that match. The code looks like this, running in a powershell script called by a Jenkins declarative pipeline, that has already downloaded a tar.gz
of the inspec profile:
# This script gets nodes from the chef server with the fqdn and tags attributes, then runs inspec on them.
# The fqdn is useful since we'll be talking to various domains.
# Note: it's important that every node has at least one tag *other than* the environment tag. Otherwise the $taglist creation won't work right.
$ErrorActionPreference = 'SilentlyContinue'
# Jenkins pipeline parameters are available as env vars
$targetEnv = $env:targetEnv
$testProfile = $env:testProfile
# Specifying json format output lets us easily convert to a hashtable object.
# Note: `-AsHashtable` requires Powershell 6 or greater
$nodesj = knife search "tags:$targetEnv" -a fqdn -a tags -F json | ConvertFrom-Json -AsHashtable
# foreach row's key, which is the node name:
$nodesj.rows.keys | ForEach-Object {
# get the data at that row
$node = $nodesj.rows.$_
# get the fqdn of that machine
$machine = $node.fqdn
# create an array with the tags that aren't the env name
$tagArr = @($($node.tags -notlike("$targetEnv")))
# create an array "[tag] [up|down]" for each node type tag
# which matches to names of the controls
$controlList = @()
foreach($tag in $tagArr) {
$controlList += "'$tag $env:upDown'"
}
$controls = "$controlList"
# finally, run inspec on the node with the proper parameters
# if the --input list gets too long, create an input file
inspec exec *.gz --target winrm://$machine --user $env:creds_USR --password $env:creds_PSW --controls=$controls --input svc_acct_name=$env:svcAcct
}
I can't edit the post above, but as you can see i don't use the regex any more, i create a list of the actual names.