Chef Provisioning Variables / Attributes

I have a question about creating multiple environments with Chef Provisioning [AWS].

Say I wanted to use Chef provisioning to do something like this:

aws_security_group sg_name do
vpc node[‘vpc’][‘id’]
inbound_rules [
{ port: 22, protocol: ‘TCP’, sources: [node[‘vpc’][‘cidrblock’]] },
{ port: -1…-1, protocol: ‘ICMP’, sources: [node[‘vpc’][‘cidrblock’]] },
{ port: 123, protocol: ‘UDP’, sources: [node[‘vpc’][‘cidrblock’]] }
action [:create]

Where can I store the attributes for this resource so that when I run Chef Provisioning I can determine which “environment” (I use that term loosely here) is used? Assume that our QA has one VPC ID and UAT is a different VPC ID with different IP address ranges.

Any ideas or help is appreciated!

When you create a VPC via chef provisioning, it will create a data bag for it.
(similarly for subnets. ).

I’m guessing from what you’ve said you have existing VPCs, and want to figure out how best to leverage them with Chef provisioning.

The easiest thing to do I think is to create data bags by hand for the existing VPCs and Subnets, as that will let you leverage all of chef provisioning.

Looking at an existing VPC created by chef provisioning:

$ knife data bag show aws_vpc

you can see the structure of it from:

$ knife data bag show aws_vpc dev-us-west-2 -F json
Unencrypted data bag detected, ignoring any provided secret options.
  "id": "dev-us-west-2",
  "reference": {
    "id": "vpc-abcdefgh"
  "driver_url": "aws::us-west-2"

So to replicate this for a new VPC, simply create a new JSON file:

$ cat newdev-us-west-2.json 
  "id": "newdev-us-west-2",
  "reference": {
    "id": "vpc-12345678"
  "driver_url": "aws::us-west-2"

and then upload it to Chef server:

knife data bag from file aws-vpc newdev-us-west-2

In my case the VPC naming matches up to environment (as that feels like a logical match) and so I can then reference the VPC via that name, so you can modify the as_security_group stanza accordingly

aws_security_group sg_name do
  vpc node.chef_environment

You can then do the same for the subnets (see aws_subnet data bag).

One thing to note, I’m using chef server, although I’d imagine this’d work the same for Chef Zero. Other thing to note, right now I’ve a chef provisioning node per environment (node.chef_environment will match that of the provisioning node)

hope this helps


Andrew, thank you for the pointer! I understand that you’re provisioning a Chef server per environment…I was hoping to avoid that for fear that keeping recipes up-to-date across many Chef servers will become an administrative burden.

oh no, you don’t need a chef server per environment!! - I just have a chef provisioning node per environment.

For me a chef provisioning node is just a local chef client which has been configured - on my laptop - to provision a dev environment I run

$ chef-client -c ~/.chef/dev-provisioner.rb -o "recipe[env-provisioning]" .

(and then I have another client configuration for a production node etc ) - its perhaps not ideal, but has provided the cleanest way for me to map to environments. - I guess you could run it with -E to specify the environment each time, but this helps me not accidentally fat finger.

See Joshua’s blog post on this here:

Although NB - knife-acl has changed a little since then - see below for show to do it with more recent versions of knife-acl

chef gem install knife-acl knife client create -d dev-provisioner > ~/.chef/dev-provisioner.pem knife node create -d dev-provisioner knife group create provisioners knife acl add group provisioners containers data create,read,update,delete,grant knife acl add group provisioners containers clients create,read,update,delete,grant knife acl add group provisioners containers nodes create,read,update,delete,grant knife group add client dev-provisioner provisioners

Thank you! I understand what you mean now – this looks great. I will give it a go!