Blog-S_Cloud-Compliance_100x385

Quick Tip: Create a Provisioner Node

This post originally appeared on jtimberman’s Code Blog.

This quick tip is brought to you by my preparation for my ChefConf talk about using Chef Provisioning to build a Chef Server Cluster, which is based on my blog post about the same. In the blog post I used chef-zero as my Chef Server, but for the talk I’m using Hosted Chef.

In order for the Chef Provisioning recipe to work the provisioning node – the node that runs chef-client – needs to have the appropriate permissions to manage objects on the Chef Server. This is easy with chef-zero – there are no ACLs at all. However in Hosted Chef, like any regular Chef Server, the ACLs don’t allow nodes’ API clients to modify other nodes, or API clients.

Fortunately we can do all the work necessary using knife, with the knife-acl plugin. In this quick tip, I’ll create a group for provisioning nodes, and give that group the proper permissions for the Chef Provisioning recipe to create the machines’ nodes and clients.

First of all, I’m using ChefDK, and it’s my Ruby environment too, so install the gem:

[ruby]chef gem knife-acl[/ruby]

Next, use the knife group subcommand to create the new group. Groups are a number of users and/or API clients. By default, an organization on Hosted Chef will have admins, billing-admins, clients, and users. Let’s create provisioners now.

[ruby]knife group create provisioners[/ruby]

The Role-based access control (RBAC) system in the Chef Server allows us to assign read, create, update, grant, and delete permissions to various objects in the organization. Containers are a special holder of other types of objects, in this case we need to add permissions for the clients and nodes containers. This is what allows the Chef Provisioning recipe’s machine resources to have their Chef objects created.

[ruby]for i in read create update grant delete
do
knife acl add containers clients $i group provisioners
done

for i in read create update grant delete
do
knife acl add containers nodes $i group provisioners
done
[/ruby]

Next, we need the API client that will be used by the Chef Provisioning node to authenticate with the Chef Server, and the node needs to be created as well. By default the client will automatically have permissions for the node object that has the same name.

[ruby]knife client create -d chefconf-provisioner > ~/.chef/chefconf-provisioner.pem
knife node create -d chefconf-provisioner
[/ruby]

Finally, we need to put the new API client into the provisioners group that was created earlier. First we need to get a mapping of the actors in the organization. Then we can add the client to the group.

[ruby]knife actor map
knife group add actor provisioners chefconf-provisioner
[/ruby]

The knife actor map command will generate a YAML file like this:

[ruby]—
:user_map
:users:
jtimberman: 12345678901234567890123456780123
:usags:
12345678901234567890123456780123: jtimberman
:clients:
chefconf-provisioner: chefconf-provisioner
jtimberman-chefconf-validator: jtimberman-chefconf-validator
[/ruby]

This maps users to their USAG and stores a list of clients. More information about this is in the knife-acl README

At this point, we have a node, with the private key in ~/.chef that can be used with the Chef Server to use Chef Provisioning’s machine resource. We can also perform additional tasks that require having a node object, such as create secrets as Chef Vault items:

[ruby]knife vault create secrets dnsimple -M client -J data_bags/secrets/dnsimple.json -A jtimberman -S ‘name:chefconf-provisioner'[/ruby]

The entire series of commands is below.

[ruby]chef gem knife-acl
knife group create provisioners

for i in read create update grant delete
do
knife acl add containers clients $i group provisioners
done

for i in read create update grant delete
do
knife acl add containers nodes $i group provisioners
done

knife client create -d chefconf-provisioner > ~/.chef/chefconf-provisioner.pem
knife node create -d chefconf-provisioner
knife actor map
knife group add actor provisioners chefconf-provisioner

knife vault create secrets dnsimple -M client -J data_bags/secrets/dnsimple.json -A jtimberman -S ‘name:chefconf-provisioner’
[/ruby]

Hopefully this helps you out with your use of Chef Provisioning, and a non-zero Chef server. If you have further questions, find me at ChefConf!

Posted in:

Joshua Timberman

Joshua Timberman is a Code Cleric at CHEF, where he Cures Technical Debt Wounds for 1d8+5 lines of code, casts Protection from Yaks, and otherwise helps continuously improve internal technical process.