Chef-Guard protects your Chef server from untested and uncommitted cookbooks

Some background info…

Before explaining al the configurable options of this rather big feature in more detail, let’s first spend a few minutes on the thoughts and reasoning behind this feature. It will set the stage and will probably answer most questions about the choices we made when designing it.

One of the biggest risks we have seen when running Chef in business critical production environments, is that there is no way to tell what cookbook code is actually being uploaded to your Chef Server. Yes every cookbook has a version, but unfortunately there is no way to tell if the person who is uploading the cookbook didn’t make any changes that are not yet committed back to the original source cookbook repo/project (i.e. that have been reviewed and made auditable) prior to uploading the altered cookbook.

And of course we know and understand that we are all perfect programmers who write lot’s of beautiful tests and run at least Test Kitchen, Foodcritic and Rubocop before even thinking about uploading a cookbook to our sacred Chef Server… Uuh… NOT!! I’m just kidding of course! Of course there are cookbook developers out there that do exactly this, but there are probably even more DevOps/Ops engineers (with less programming experience) who don’t follow this process as closely as one would like.

I can probably write a book about all the different problems and frustrations you will run into as soon as someone in your organization starts doing cookbook uploads with untested or uncommitted code, but I guess that most of you have experienced one or more of these examples yourselves already…

So this feature is all about making sure that whatever is uploaded into your Chef Server is something that is shared, committed and tested so that it’s auditable and everybody in your organization knows where to find the source of the cookbooks used in your Chef environment. Make sure you also have a look at the Cookbook Upload Workflow that gives a graphical overview of the complete workflow containing this feature, including the impact of the configurable options.

Cookbook Validation

The cookbook validation feature is responsible for actually validating that the cookbook is tested and that the cookbook code is either committed into a known cookbook repo/project or is an existing artifact, before passing the cookbook on to your Chef Server/Organization. Some of the steps described below are configurable options that can impact the way the validation feature works. For more details about these options check the Cookbook Upload Workflow or the Chef-Guard configuration section.

Comparing the cookbook

In order to validate that the cookbook code is committed or is an existing artifact, the uploaded cookbook is compared against either one. For this Chef-Guard needs to find a matching cookbook/version to do the comparison against. This is done by first contacting the community Supermarket to check if the cookbook/version combination being uploaded already exists. If not, your private Supermarket (if configured) is also searched. When Chef-Guard finds a match it uses the matching artifact for the comparison.

If no match is found, Chef-Guard will search for the cookbook repo/project in all configured GitHub organizations and GitLab groups. When a matching repo/project is found, Chef-Guard will also try to find a matching tag. If it finds one, the tagged version will be used for the comparison. If it doesn’t find one the cookbook will be compared against HEAD of the matching repo.

If no matching artifact if found at either the community- or private Supermarkets and no matching repo or project is found in any of the configured GitHub organizations and GitLab groups, Chef-Guard will return with a 412 Precondition Failed error and some additional details about the error. In this case the cookbook will not be uploaded!

Assuming that the source cookbook can be found, Chef-Guard will then compare the source cookbook against the cookbook being uploaded. If there if a diff between the cookbooks Chef-Guard will again return a 412 Precondition Failed and will not upload the cookbook. Only when the cookbooks are completely in sync, Chef-Guard will proceed with the validation.

When the comparison succeeds and the matching cookbook was found in an untagged repo or project, Chef-Guard will now tag this repo/project with the used version. This will make sure that the cookbook/version being uploaded into your Chef Server/Organization can always be retrieved/found in your GitHub repo or GitLab project.

Publishing the cookbook

If you don’t have a local Chef Supermarket installation, this is currently probably the best you can do in in order to manage the version of your private cookbooks. But if you have gone the extra mile and also have a local Supermarket installation, your are in for a treat!

In that case Chef-Guard can be configured to upload the cookbook directly to your local Supermarket. By doing so you now have a clean artifact of the cookbook that is being frozen for future use.

NOTE: Of course another big advantage of having your cookbook directly uploaded to the local Supermarket, is that all your colleagues who are using the local Supermarket to search for existing private cookbooks, can now instantly find the new cookbook!

Testing the cookbook

The only sensible way for Chef-Guard to make sure that a cookbook is tested, is by running the tests itself. So that is exactly what Chef-Guard is doing when a cookbook that is uploaded is being frozen. Currently you can configure Chef-Guard to execute the following tests:

  • Foodcritic
  • Rubocop

If one of the checks fails Chef-Guard will return a 412 Precondition Failed. The additional error details will describe the failed test, giving direct feedback to the colleague uploading the cookbook. This will not only help to improve your organizations cookbooks, but it will also help your colleagues to become better cookbook developers at the same time.

Whether or not the cookbook will be uploaded after a failed test depends on how Chef-Guard is configured and which flags are passed during the upload. As described in the Overview section the knife option --force is changed and is now used in conjunction with these tests. When the effective mode for your Chef Server/Organization is set to ‘permissive’ and the --force option is passed, Chef-Guard will upload the cookbook despite of the failed tests. If however the effective mode is set to ‘enforced’, the cookbook will not be uploaded when a test has failed!