Technical Article => Programming => Ruby

While using Chef, one would frequently use knife commands which are used to manage resources on the Chef server. One can list all nodes, data bags, vault items and many other stuff on the Chef server. In this post, we would cover one command which may need your attention when using it -- knife vault.

On Chef server, one can store data to data bags which can be accessed by registered clients. These data bags usually store the data in plain text format. In some cases, one would need to store data secretly on the Chef server, Chef provides the encrypted data bag which uses a shared symmetric secret to encrypt the data. However, this mechanism brings up a long-term key distribution problem. How can the shared secret be distributed to the clients safely? Encrypted data bag itself doesn't offer a way of key distribution. Hence Chef vault comes to the save.

Basically how Chef vault works is that it will encrypt the shared secret using the public key of the registered clients and store them in the corresponding data bag keys file. Then the client who want to access the encrypted data bag will first get to check whether it can use its private key(client.pem) to decrypt the shared secret stored in the keys file. If it can, then it will use the decrypted shared secret to decrypt the data bag item. Otherwise, exception will be raised. The details of how Chef vault works can be read at Chef Vault – what is it and what can it do for you?.

Along with Chef vault, there is a knife command provided -- knife vault. This command can be used to check the Chef vault information on the Chef server. It can be used to show, create, update, remove items stored on the Chef server. And it works like other knife commands provided by Chef. However, there is a major difference in its default behavior.

While using other knife commands, they will contact Chef server by default to get the requested information. However, knife vault will not contact Chef server by default. Instead it will operate on the local cache.

Let's take an example of list some data bag items. First using knife data bag show. The command executed is

knife data bag list -VV

The output looks like

bash-4.1$ knife data bag list -VV INFO: Using configuration from /home/test/.chef/knife.rb DEBUG: Chef::HTTP calling Chef::HTTP::JSONInput#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::JSONToModelOutput#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::CookieManager#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::Decompressor#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::Authenticator#handle_request DEBUG: Signing the request as cobalt DEBUG: Chef::HTTP calling Chef::HTTP::RemoteRequestID#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::ValidateContentLength#handle_request DEBUG: Initiating GET to https://IBMSASG1.cin.pt/organizations/cobalt/data DEBUG: ---- HTTP Request Header Data: ----

The command is contacting the Chef server by sending HTTP request. Next, let's run the knife vault command. The command executed is

knife vault show vault1 item1 -VV

The output looks like

bash-4.1$ knife vault show vault1 item1 -VV INFO: Using configuration from /home/test/.chef/knife.rb INFO: Unable to access cache at /var/chef. Switching cache to /home/test/.chef INFO: Unable to access cache at /var/chef. Switching cache to /home/test/.chef /home/test/.rvm/gems/ruby-2.2.2/gems/chef-vault-2.5.0/lib/chef-vault/item_keys.rb:125:in `rescue in load': vault1/item1_keys could not be found (ChefVault::Exceptions::KeysNotFound)

From the output, there is no HTTP request sent. Instead, it's looking for the cache and failed to find it.

Why so big difference? The knife vault command doesn't contact the chef server at all. It is solely trying to load the data bags from local environment. This happens because chef-vault author sets the DEFAULT MODE to solo when knife vault command is executed. In this case, solo means to work locally. While knife data bag will contact chef server by default.

To make knife vault contact chef server, below command can be executed(with an option -M client added).

knife vault show vault1 item1 -VV -M client

The output now looks like

bash-4.1$ knife vault show vault1 item1 -VV -M client INFO: Using configuration from /home/test/.chef/knife.rb DEBUG: Chef::HTTP calling Chef::HTTP::JSONInput#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::JSONToModelOutput#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::CookieManager#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::Decompressor#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::Authenticator#handle_request DEBUG: Signing the request as cobalt DEBUG: Chef::HTTP calling Chef::HTTP::RemoteRequestID#handle_request DEBUG: Chef::HTTP calling Chef::HTTP::ValidateContentLength#handle_request

Now it looks familiar. It contacts the Chef server.

One thing to point out. If invoking chef-vault from ruby code, there will be no problem since the default mode is set only when knife vault commands are executed.

In conclusion, knife vault is behaving something differently than other knife commands. So be careful.