Restricting User Access to Nodes

We are just starting to roll out chef, and I was wondering how people were managing user access to nodes. Our environment is set up to have multiple administrators managing their own set of nodes, but we want to prevent one person from accidentally changing the configuration of another person’s nodes. I am curious what other chef users are doing to help lock down user changes.

Sounds like a good use case for environments.

Nathan Clemons

DevOps Engineer

Moxie Cloud Services (MCS)

O +1.425.467.5075

M +1.360.861.6291

E nclemons@gomoxie.com

W www.gomoxie.comhttp://www.gomoxie.com/

That was the first thing I looked into, but the amount of separate environments will quickly get unmanageable for those in charge of managing the base cookbooks (the ones run on every node). Unless we are missing something…

The only way to truly isolate multiple administrators is to give them their own chef organization.
If these are development machines, you may be better off using chef-zero or test-kitchen to give developers their own isolated environments.

The way we handle this problem is to not allow anyone to edit nodes through the web interface, and instead put all configs as json inside a git repo. This way, the git server then becomes the ACL.

We have development machines managed by IT (because windows vms are hard to self service when they require AD integration). Approved developers can edit the json configs, but only on non protected branches (.e.g. master). They then create a merge request inside gitlab.

gitlab-ci validates the json and then runs knife upload. The whole process takes about 30 seconds. Its a few more steps than allowing admins to make changes in the chef manage web interface, but it is far safer and has an audit trail.

Here is a .gitlab-ci.yml file from a test server that shows the commands that the gitlab-ci vm runs:

image: ruby:2.2

variables:
  CHEF_KEY_FILE: "/some/random/directory/gitlab-ci.pem"

stages:
  - test
  - deploy

before_script:
  - echo "$LAB_CHEF_KEY" > "$CHEF_KEY_FILE"

test:json:
  stage: test
  script:
    - echo "Checking roles/env have valid json"
    - bundle install --jobs=3
    - rake jsonlint

lab:environments:
  stage: deploy
  image: netdocuments/chefdk
  script:
    - /usr/bin/knife upload --concurrency 15 --server-url $LAB_CHEF_SERVER -u $LAB_CHEF_USER -k $CHEF_KEY_FILE -V --chef-repo-path . environments
    - rm $CHEF_KEY_FILE
  only:
    - master

lab:roles:
  stage: deploy
  image: netdocuments/chefdk
  script:
    - /usr/bin/knife upload --concurrency 15 --server-url $LAB_CHEF_SERVER -u $LAB_CHEF_USER -k $CHEF_KEY_FILE -V --chef-repo-path . roles
    - rm $CHEF_KEY_FILE
  only:
    - master

lab:data_bags:
  stage: deploy
  image: netdocuments/chefdk
  script:
    - /usr/bin/knife upload --concurrency 15 --server-url $LAB_CHEF_SERVER -u $LAB_CHEF_USER -k $CHEF_KEY_FILE -V --chef-repo-path . data_bags
    - rm $CHEF_KEY_FILE
  only: 
    - master

You could use environments and if they are written in ruby then you can use Mixin. Put in all your base settings in your an separate ruby file then mix that in with

from_file File.expand_path("common/base.rb", File.dirname(__FILE__))

$dev_attributes = {
  "somejunk" => {
        "junk_version" => '1.2.3'
      }
    }
}

default_attributes(Chef::Mixin::DeepMerge.deep_merge($dev_attributes,$base_attributes))

This works well for us as we have base settings that apply to all environments but then we have an few attributes that we want to change as the software moves it way thru environments.