Reputation: 837
After some chef zero runs (which save the node state as local .json files) I was dismayed to find this in the node files:
...
"ssmtp": {
"auth_username": "secret user name",
"auth_password": "even-more-secret password"
}
The same runs on Chef Server would save the node data on the server. That's is a problem of course, and I'll have to replace credentials, modify the recipes, etc. I am still investigating what caused this in the first place but my question is:
How I can create an rspec/chefspec test for a recipe to verify that a particular node attribute is NOT saved persistently in the node's .json file or on Chef Server?
I'd like to add this to my specs to make sure it never happens again.
The big lesson here is that anything finding its way into any node attribute winds up being saved in the node object representation.
Upvotes: 0
Views: 2660
Reputation: 165
Chef Server will save all attributes, even if they are normal or default or another precedence level. You can get around this by using node.run_state which can be used to "stash transient data during a chef-client run."
You can see this at work in the elkstack community cookbook, most notably in the _lumberjack_secrets.rb recipe.
node.run_state
being set:
if <CONDITION ABBREVIATED>
node.run_state['lumberjack_decoded_key'] = Base64.decode64(lumberjack_secrets['key'])
....
end
node.run_state
being used:
lumberjack_keypair = node.run_state['lumberjack_decoded_key'] && node.run_state['lumberjack_decoded_certificate']
As for the test, I haven't "tested" this myself, but you would be testing to make sure the attribute is not set, like this:
it 'should not have secret attributes set' do
node = chef_run.node
expect (node['my_secret']).to be_nil
end
Upvotes: 2
Reputation: 837
The key is in the comment from the Chef docs, "A normal attribute is a setting that persists in the node object. A normal attribute has a higher attribute precedence than a default attribute." That breaks the problem down into testing if an attribute is a "normal" attribute.
Digging into the Chef::Node and Chef::Node::Attribute class code, I found you can call node.attributes.normal
to get just the the normal attributes. So this concise test correctly fails, indicating that my secret info is going to be stored persistently in the node object!
it 'does not have a normal attribute node[ssmtp][auth_password]' do
expect(subject.node.attributes.normal['ssmtp'].keys).to_not include 'auth_password'
end
resulting in this decent error message:
Failure/Error: expect(subject.node.attributes.normal['ssmtp'].keys).to_not include 'auth_password'
expected ["auth_username", "auth_password"] not to include "auth_password"
You could also test to that if a specific value is not set, but I think testing that the key does not exist is more to the point.
Somehow I always get new insights from simply formulating a question to post here. So it goes.
Upvotes: 0