Minimal Access Controls for Uploading Cookbooks to a Chef Infra Server (Updated)

Chef

Update: I needed to further restrict the permissions so I’ve rewritten this post.

The CI/CD system I was working with needed to have a temporary client with limited permissions for uploading cookbooks. While Chef Infra Server has extensive access controls, the knife-acl documentation didn’t provide an example of what I needed, so I’m documenting it here.

Chef Server Preparation

These commands must be run on the Chef Server. First, we’ll create the organization for testing:

chef-server-ctl org-create test1 'Test Organization 1' -f test1-validator.pem

Because I’m using a self-signed certificate and not every knife subcommand takes --node-ssl-verify-mode, I have this additional no_ssl.rb configuration file. You may not need this step if you have a proper certificate.

ssl_verify_mode :verify_none

Create a cookbook-uploader Group

A group is used to define access to objects in the Chef Infra Server. We will do this from the Chef Server with the pivotal superadmin user. I want to restrict the permissions for this group to only allow uploading a cookbook. We will create a cookbook-uploader group that will have permissions for cookbook uploading but nothing else. This requires create permissions on the cookbooks container and create on the sandboxes container for uploading.

knife group create cookbook-uploader --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" --disable-editing -c no_ssl.rb
knife acl add group cookbook-uploader containers cookbooks create --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb
knife acl add group cookbook-uploader containers sandboxes create --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb

You can verify these permissions with the following (note the cookbook-uploader):

$ knife acl show containers cookbooks --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb
create:
  clients:
  groups:
    admins
    cookbook-uploader
    users
  users:   pivotal
delete:
  clients:
  groups:
    admins
    users
  users:   pivotal
grant:
  clients:
  groups:  admins
  users:   pivotal
read:
  clients:
  groups:
    admins
    clients
    users
  users:   pivotal
update:
  clients:
  groups:
    admins
    users
  users:   pivotal

Create the cookbook client creator client

Next we need to create a ccc client that can create other clients.

knife client create ccc -f ccc.pem --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb --disable-editing
knife acl add client ccc containers clients create --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb

The ccc client can add clients to the cookbook-uploader group.

knife acl add client ccc groups cookbook-uploader read --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb
knife acl add client ccc groups cookbook-uploader update --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb

We’re now done with this organization on the Chef Infra Server. Copy the the ccc.pem off the Chef Infra Server as necessary.

Reusing the ccc client across multiple organizations

Having a ccc client that can create clients in a particular organization is useful, but if you had a large number of organizations you’d probably prefer to reuse that privileged client across them. knife client create will allow you to provide your own public key, so the following can be used to create the public key from the generated private key, then reuse it for additional organizations (in our case test2).

chef-server-ctl list-client-keys test1 ccc -v | tail -10 > ccc.pub
knife client create ccc --public-key ccc.pub --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test2" -c no_ssl.rb --disable-editing

From here out, the rest of the commands with the ccc client would be the same, replacing test1 with test2 or whatever you organizations may be named.

Create the upload client

Now that ccc can make clients and add them to cookbook-uploader group, we will use this to create new clients for uploading. Rather than have a permanent user for managing uploads, I’m going to create a temporary client.

$ knife client create upload1 -f upload1.pem --key ccc.pem --user ccc --server-url "https://CHEFSERVER/organizations/test1" -c no_ssl.rb --disable-editing
Created client[upload1]

Add the client to cookbook-uploader group.

$ knife group add client upload1 cookbook-uploader --key ccc.pem --user ccc --server-url "https://CHEFSERVER/organizations/test1" -c no_ssl.rb
Adding 'upload1' to 'cookbook-uploader' group

We can verify that the client is part of the cookbook-uploader group.

$ knife group show cookbook-uploader --key ccc.pem --user ccc --server-url "https://CHEFSERVER/organizations/test1" -c no_ssl.rb
actors:    upload1
clients:   upload1
groupname: cookbook-uploader
groups:
name:      cookbook-uploader
orgname:   test1
users:

Upload a Cookbook

Now that the temporary user is in place, they can upload the cookbook.

$ knife cookbook upload apt -o cookbooks --key upload1.pem --user upload1 --server-url "https://CHEFSERVER/organizations/test1" -c no_ssl.rb
Uploading apt          [7.3.0]
Uploaded 1 cookbook.

This user has permission to list cookbooks, but not view any others that were not created by .

$ knife cookbook list --key upload1.pem --user upload1 --server-url "https://CHEFSERVER/organizations/test1" -c no_ssl.rb
apt     7.3.0

Delete the client

Once the CI/CD has finished uploading the cookbook, the client can be deleted.

$ knife client delete upload1 --key upload1.pem --user upload1 --server-url "https://CHEFSERVER/organizations/test1" -c no_ssl.rb -y
Deleted client[upload1]

Verifying on the Chef Infra Server

Here are a few commands for reference if you need to look at the clients and groups on the Chef Infra Server:

chef-server-ctl org-list
knife client list --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb
knife group list --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb
knife group show cookbook-uploader --key /etc/opscode/pivotal.pem --user pivotal --server-url "https://localhost/organizations/test1" -c no_ssl.rb