0

I have the following user credentials in my chef vault

$ knife vault show testusers
user1
user2
user3

The content of each individual user looks like this:

knife vault show testusers user1
comment:  user one
id:       user1
password: secretp@ss
shell:    /bin/bash

I am trying to write a recipe that will loop through my testuser vault and create users based on each vault item's ID. That way i can easily update the testuser vault with new users and rerun the recipe in order to add users in the future.

Here is a copy of the recipe i have created thus far but it isn't working

chef_gem 'chef-vault' do
  compile_time true if respond_to?(:compile_time)
end

require 'chef-vault'

if node['testcookbook']['testusers'] == true then
    users = data_bag(node['testcookbook']['testusers'])
    users.each do |id|
        user = ChefVault::Item.load(node["testcookbook","testusers"], id)
        testusers user['id'] do
            comment user['comment']
            shell user['shell']
            password user['password']
        end
    end

Can someone please tell me what i am doing wrong here? Everything seems to look fine from the numerous research i have done.

Edit

I tried your solution and the following error message.

Chef::Exceptions::InvalidDataBagName

------------------------------------

DataBags must have a name matching /^[\.\-[:alnum:]_]+$/, you gave ""

chef_gem 'chef-vault' do
  compile_time true if respond_to?(:compile_time)
end
require 'chef-vault'

17>>    users = data_bag(node['testcookbook']['testusers']).delete_if {|x| x.include? "_keys" }
     users.each do |id|
           user = ChefVault::Item.load(node["testcookbook","testusers"], id)
            testcookbook testusers['id'] do
                   comment testusers['comment']
                   uid testusers['uid']
                   shell testusers['shell']
                   password testusers['password']
              end 

[2016-08-22T19:24:58-04:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
[2016-08-22T19:24:58-04:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2016-08-22T19:24:58-04:00] ERROR: DataBags must have a name matching /^[.-[:alnum:]_]+$/, you gave ""
[2016-08-22T19:24:58-04:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)`

StephenKing
  • 36,187
  • 11
  • 83
  • 112
jebjeb
  • 115
  • 1
  • 4
  • 12

2 Answers2

1

You haven't given details of what is not working. I suspect Priya is correct that your issue is that you should be reading using the vault API rather than looping thru the data bag.

I also notice you haven't considered how users would be deleted...


Have you considered using SSH based key authentication, instead of using passwords? In my opinion this would a far superior way to manage users since it avoids the need to share a password with a system administrator. An SSH public key is designed to be sharable with the private key remaining known only to the user.

I mention this because the community users cookbook is designed to implement your desired workflow with each user record stored in a data bag. An example of its use is given here:

Community
  • 1
  • 1
Mark O'Connor
  • 76,015
  • 10
  • 139
  • 185
0

IMHO, doing simple databag call on vault will list the encryption keys as well which might result into failure. for example,

My vault has only one item named "root",

$knife vault show mrigesh
root

And, accessing vault in the recipe will return an array, with vault and its keys as separate elements:

users = data_bag("mrigesh")
puts users
root
root_keys

Hence, iterating on this result will try to search for vault named "root_keys" which is not there resulting into failure.

To solve, you can do something like:

node.default['testcookbook']['testusers'] = "testusers"
users = data_bag(node['testcookbook']['testusers']).delete_if {|x| x.include? "_keys" }
users.each do |id|
      user = ChefVault::Item.load(node['testcookbook']['testusers'], id)
      testusers user['id'] do
         comment user['comment']
         shell user['shell']
         password user['password']
      end

end
  • Thanks Mrigesh- I have edited the post to show the error i got while trying your solution. – jebjeb Aug 23 '16 at 00:12
  • I am not sure, what you are trying to do. Here the "node['testcookbook']['testusers']" is working as boolean : "if node['testcookbook']['testusers'] == true" Then you treat it as databag name: data_bag(node['testcookbook']['testusers']) Its causing the error. – Mrigesh Priyadarshi Aug 23 '16 at 03:14
  • I am actually trying to create a recipe that will create users based on the number of items in my vault. In order words if i have 5 items(user1,user2,user3,user4,user5),in the testusers vault, the recipe should be able to loop thru that vault and create users based on the information stored in each vault item. I made some additional changes based on your suggestion but now im stuck at ERROR: wrong number of arguments (2 for 1) on line 17 which is user = ChefVault::Item.load(node["testcookbook","testusers"], id). – jebjeb Aug 23 '16 at 14:31
  • Looks like my formatting issue and you are just copy and pasting it. ;) Updated the answer. – Mrigesh Priyadarshi Aug 23 '16 at 16:38
  • Thanks for the help Mrigesh. I fixed the formatting. Unfortunately i am now getting an ERROR: No resource or method named 'testusers' for `Chef::Recipe "default'. Dont know why its saying this since the variable node.default['testcookbook']['testusers'] = "testusers" is already defined. – jebjeb Aug 23 '16 at 19:39
  • Please open a separate question. – Mrigesh Priyadarshi Aug 24 '16 at 03:02