Restricting what a client can read via ACL's

I have a security requirement to restrict what a Chef client can read. Specifically a client should not be able to read Node objects other than its own, and should only have access to one data bag item in a large data bag. I’m using Open Source Chef 12 and Chef client, both the latest versions.

Is this possible with ACL’s? In theory from what I read it may be possible but I can’t get anything to work.

thanks!
mike

Not sure about the ACL side of things, but keep in mind that this will
break any kind of chef search.

-Grant

Absolutely, that’s a given. Security is more important than search in this scenario.

thanks
mike

Changing the default ACLs can have unforeseen consequences but can be a useful tool for managing permissions and security.

You can edit ACLs for many existing objects by using Chef Manage: https://docs.chef.io/manage.html
Or change default ACLs and the ACLs for existing objects by installing knife acl plugin: https://github.com/chef/knife-acl

Some Notes On Permissions In The Chef Server

For a brief primer on ACLs, I would start here: https://docs.chef.io/auth_authorization.html

The Chef Server uses one-time inheritance for its auth model. It has a “container” that corresponds to each object type that contains the default permissions for newly created objects. You can change the defaults for new objects by editing these containers, but keep in mind that you must update existing objects for each container type if you wish your changes to be applied retroactively to existing objects.

Regardless, I would recommend testing out any ACL changes in a new org in case you make a mistake before applying them to your existing organizations.

Restricting Client Access To Nodes

As far as your specific needs, restricting clients from reading other node objects isn’t too bad. I created a new node called testnode and here is what the permissions look like:

{"actors"=>["testnode", "pivotal"], "groups"=>["clients", "users", "admins"]}

Now, let’s edit the nodes container to exclude the clients group in the default permissions for a node.

Here is the template for knife acl remove:

knife acl remove MEMBER_TYPE MEMBER_NAME OBJECT_TYPE OBJECT_NAME PERMS

So let’s remove clients from the read perm for the nodes container:

$ knife acl remove group clients containers nodes read
Removing 'clients' from 'read' ACE of 'nodes'

Now, I’ll bootstrap a new node named testnode2 and see its permissions:

{"actors"=>["testnode2", "pivotal"], "groups"=>["users", "admins"]}

There you go! The only client that has read permissions on the node testnode2 is the client testnode2!

Note that my existing node, testnode, still has the clients group in its read ACL though:

{"actors"=>["testnode", "pivotal"], "groups"=>["clients", "users", "admins"]}

To fix that, you’d need to update the ACL for every existing node. You could do that with knife acl bulk:

knife acl bulk remove group clients nodes '.*' read -y

Careful though! This will edit every node you have in the org…

Now if we look at testnode’s permissions:

{"actors"=>["testnode", "pivotal"], "groups"=>["users", "admins"]}

It is correct and now correct for all existing nodes.

Note that you can check permissions for any object with knife acl show (I was using chef-shell and hitting the _acl API, but it does the same thing, output might be slightly different though).

Restricting Data Bag Access

As far as “[clients] should only have access to one data bag item in a large data bag” goes, things get a bit tricker. I’m assuming you mean each client should only have access to a single data bag item that other clients do not have access to.

Currently, data bags have ACLs, but data bag items do not; therefore, you cannot let a client access a single data bag item. You can only change a client’s access to an entire data bag. An actor either has access on all data bag items within a data bag, or none.

A possible workaround would be to remove clients from the read perms for the data container similar to what we did for the nodes container above, and then create a data bag per client and grant read on the specific data bag corresponding to client. That way, each client would have a data bag they could read from, but they couldn’t access the other data bags.

Is there a reason you want one large data bag with specific items a client can read vs separate data bags per client? If the answer is no, I can walk you through setting up what I just described.

Thank you Tyler for the extremely detailed response, greatly appreciate it! I’m going to dig into this further and see if we can make it work for our use case.

Regarding the data bags, I’m not sure what the implications are in our use case for having one data bag per group of nodes instead of one data bag with one item per group of nodes. Assuming we can switch to multiple data bags, is there an upper limit of number of data bags? I’d currently need 100+ with that scaling upwards to 1000+ eventually.

thanks!
mike