Closed lonniev closed 3 years ago
Here's the concept gist. This looks for all users in the bags that users
currently uses that have a true
value for has_private_ssh
. For each of those, it loads their key values from the encrypted private_keys bag that shares their users:id
name.
Some of the steps are redundant with what manage_users
will do and the code is in the midst of debug--but it expresses the goal.
# for each user with an has_private_ssh entry, create their ssh identity files
search( "users", "has_private_ssh:true AND NOT action:remove") do |ssh_user|
ssh_user['username'] ||= ssh_user['id']
ssh_keys = Chef::EncryptedDataBagItem.load( "private_keys", ssh_user['id'] )
if ( ssh_keys.empty? )
log "message" do
message "user #{ssh_user['id']} missing from data_bags/private_keys."
level :warn
end
next
end
sshDir = Pathname.new( ssh_user['home'] ).join( ".ssh" )
idFile = sshDir.join( "id_rsa" )
directory sshDir.to_s do
owner ssh_user['username']
group ssh_user['username']
mode 0700
recursive true
action :create
end
file sshDir.join( "config" ).to_s do
owner ssh_user['username']
group ssh_user['username']
mode 0600
content <<-EOT
Host *
StrictHostKeyChecking no
IdentityFile #{idFile}
IdentitiesOnly yes
EOT
end
file idFile.to_s do
owner ssh_user['username']
group ssh_user['username']
mode 0600
content ssh_keys['private']
end
file idFile.sub_ext( ".pub" ).to_s do
owner ssh_user['username']
group ssh_user['username']
mode 0644
content ssh_keys['public']
end
end
What about something like this?
use_inline_resources if defined?(use_inline_resources)
def whyrun_supported?
true
end
def userlist
secret_key = Chef::EncryptedDataBagItem.load_secret(Chef::Config[:encrypted_data_bag_secret])
dec_users = []
data_bag(:users).each do |user|
dec_users << Chef::EncryptedDataBagItem.load("users", "#{user}", secret_key)
end
return dec_users
end
def initialize(*args)
super
@action = :create
end
def chef_solo_search_installed?
klass = ::Search::const_get('Helper')
return klass.is_a?(Class)
rescue NameError
return false
end
action :remove do
userlist.each do |rm_user|
if rm_user['groups'].first == "#{new_resource.search_group}" and rm_user['action'] == "remove"
user "#{rm_user['id']}" do
action :remove
end
end
end
end
action :create do
security_group = Array.new
userlist.each do |u|
if u['groups'].first == "#{new_resource.search_group}" and not u['action'] == "remove"
security_group << u['id']
if node['apache'] and node['apache']['allowed_openids']
Array(u['openid']).compact.each do |oid|
node.default['apache']['allowed_openids'] << oid unless node['apache']['allowed_openids'].include?(oid)
end
end
# Set home_basedir based on platform_family
case node['platform_family']
when 'mac_os_x'
home_basedir = '/Users'
when 'debian', 'rhel', 'fedora', 'arch', 'suse', 'freebsd'
home_basedir = '/home'
end
# Set home to location in data bag,
# or a reasonable default ($home_basedir/$user).
if u['home']
home_dir = u['home']
else
home_dir = "#{home_basedir}/#{u['id']}"
end
# The user block will fail if the group does not yet exist.
# See the -g option limitations in man 8 useradd for an explanation.
# This should correct that without breaking functionality.
if u['gid'] and u['gid'].kind_of?(Numeric)
group u['id'] do
gid u['gid']
end
end
# Create user object.
# Do NOT try to manage null home directories.
user "#{u['id']}" do
uid u['uid']
if u['gid']
gid u['gid']
end
shell u['shell']
comment u['comment']
password u['password'] if u['password']
if home_dir == "/dev/null"
supports :manage_home => false
else
supports :manage_home => true
end
home home_dir
action u['action'] if u['action']
end
Chef::Log.debug("Managing home files for #{u['id']}")
directory "#{home_dir}/.ssh" do
owner u['id']
group u['gid'] || u['id']
mode "0700"
end
if u['ssh_keys']
template "#{home_dir}/.ssh/authorized_keys" do
source "authorized_keys.erb"
cookbook new_resource.cookbook
owner u['id']
group u['gid'] || u['id']
mode "0600"
variables :ssh_keys => u['ssh_keys']
end
end
if u['ssh_private_key']
key_type = u['ssh_private_key'].include?("BEGIN RSA PRIVATE KEY") ? "rsa" : "dsa"
template "#{home_dir}/.ssh/id_#{key_type}" do
source "private_key.erb"
cookbook new_resource.cookbook
owner u['id']
group u['gid'] || u['id']
mode "0400"
variables :private_key => u['ssh_private_key']
end
end
if u['ssh_public_key']
key_type = u['ssh_public_key'].include?("ssh-rsa") ? "rsa" : "dsa"
template "#{home_dir}/.ssh/id_#{key_type}.pub" do
source "public_key.pub.erb"
cookbook new_resource.cookbook
owner u['id']
group u['gid'] || u['id']
mode "0400"
variables :public_key => u['ssh_public_key']
end
end
else
Chef::Log.debug("Not managing home files for #{u['id']}")
end
end
group new_resource.group_name do
if new_resource.group_id
gid new_resource.group_id
end
members security_group
end
A lot of things are moving to support chef-vault now. Any thoughts on allowing that for the encrypted data bag pieces?
Submitted a PR: https://github.com/opscode-cookbooks/users/pull/91
Even edited little my code :) Nice to see :) Let's wait for merge ^)
@yl013512 so is your forked version essentially work with the existing "users_manage" resource but with a encrypted data bag of users via chef-vault?
It must. Just try from fork
@yl013512 tried your fork with a chef-vault encrypted users item and get the following error. Any ideas?
10.41.82.124 Recipe Compile Error in /var/chef/cache/cookbooks/users/providers/manage.rb 10.41.82.124 ================================================================================ 10.41.82.124 10.41.82.124 NameError 10.41.82.124 --------- 10.41.82.124 uninitialized constant Chef::Provider::ChefVaultItem 10.41.82.124 10.41.82.124 Cookbook Trace: 10.41.82.124 --------------- 10.41.82.124 /var/chef/cache/cookbooks/users/providers/manage.rb:20:in `class_from_file' 10.41.82.124 10.41.82.124 Relevant File Content: 10.41.82.124 ---------------------- 10.41.82.124 /var/chef/cache/cookbooks/users/providers/manage.rb: 10.41.82.124 10.41.82.124 13: # 10.41.82.124 14: # Unless required by applicable law or agreed to in writing, software 10.41.82.124 15: # distributed under the License is distributed on an "AS IS" BASIS, 10.41.82.124 16: # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10.41.82.124 17: # See the License for the specific language governing permissions and 10.41.82.124 18: # limitations under the License. 10.41.82.124 19: # 10.41.82.124 20>> include ChefVaultItem 10.41.82.124 21: 10.41.82.124 22: use_inline_resources if defined?(use_inline_resources) 10.41.82.124 23: 10.41.82.124 24: def whyrun_supported? 10.41.82.124 25: true 10.41.82.124 26: end 10.41.82.124 27: 10.41.82.124 28: def initialize(*args) 10.41.82.124 29: super
Any ideas when Chef Vault support will be available for this cookbook?
I think it would need to be an option for the recipe that calls the data_bag, associated with a different data_bag directory.
Is there any update on the support of encrypted data bag items?
Hi, from version 6.0.0 the data source has been moved outside of the users_manage resource. So you can now initialize your encrypted data bag in the recipe and then pass it to the manage resource.
See https://github.com/sous-chefs/users/blob/master/upgrading.md for details with a normal databag. This can easily be adapted to an encrypted data bag or any data source you want.
It would be great to have the option of supplying an encrypted data bag or a set of such bags to the
users
recipe.I have a UseCase where I automate the creation of users and their logins. For this, I need to create their initial passphrase-less private id_rsa ssh keys. Currently, I do this in a custom recipe that reads an encrypted data bag to get the encrypted content of the id_rsa file. It reads the json attribute, decrypts it, creates the ~/.ssh/id_rsa file, and stuffs it with the right content. (The recipe manages the .ssh directory and the config file as well.)
It would be great to delegate all this to the existing
users_manage
resource. That resource, as you know, does the right stuff for any found ssh_private_key attribute in the users' bags. However, it expects that private key value to be plaintext.So, if the manage resource either would look in a separate encrypted bag for such sensitive keys or would allow the entire user's bag to be encrypted, then it could manage all this ssh cruft.