Handling passwords in application cookbooks

I’d like to get the community’s feedback on how we’re handling application
passwords in the context of library and application cookbooks. This
approach seems to be working well, but others might have better ideas.

First some context. We have a single instance of Open Source Chef server
that we use for developing cookbooks, but also to manage our development
infrastructure (Jenkins, Artifactory, etc.). This means that all developers
can see the node attributes of our development infrastructure, including
any passwords that are stored there. All of what follows could be avoided
by splitting this into two Chef instances, but the question remains “what
if you don’t want passwords appearing in node attributes?”.

We do the simplest possible thing in our library cookbooks: we define
passwords as cookbook attributes at the default level, giving them
throw-away values. Then we use the attributes in recipes to render config
files, run commands, etc.

We put the actual passwords in an encrypted data bag. Then in the
application cookbook recipe, we:

  1. Read the data bag
  2. Override the library cookbook’s password attribute with the value
    from the data bag
  3. Include the library cookbook’s recipes
  4. In a ruby_block, delete the library cookbook’s password attributes.
    This must be done in a ruby_block so that it happens after any library
    cookbook activity, whether compile-time or convergence-time.

This has the following desirable qualities:

  • Library cookbooks are simple to write and test. They use attributes in
    a natural manner, for passwords and for everything else.
  • The decision to use an encrypted data bag (and which one), which we
    consider a policy decision, is properly contained in the application
    cookbook.
  • Application cookbooks follow a well-defined pattern that’s fairly easy
    for developers to understand and replicate.
  • If a Chef run fails, the real passwords don’t appear in Chef server
    because node attributes aren’t reported to Chef server after failed Chef
    runs.
  • If a Chef run succeeds, the real passwords don’t appear in Chef server
    because they’ve been deleted by the ruby_block before the run finishes.

The only issue we’ve run into is when an application cookbook’s attribute
file builds another attribute using the password, such as building a
connection string out of the password and other values. In that case the
application cookbook must duplicate the construction of the connection
string at the override-level.

Is anyone else doing something similar? What do you think of this approach?

Thanks,
Kevin Christen