Creating authorized_keys for LDAP users

I’m having trouble setting up users authorized keys. A cookbook that runs
earlier in the runlist sets up LDAP. However, due to reasons I don’t
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can’t simply
create files and directories and use ‘owner’ and 'group.

I came up with the below idea. I’m iterating over the ssh keys in a data
bag and then for each user running a command as this user. That makes PAM
do all the home directory setup for me. I create the ~/.ssh directory in a
similar fashion, as the user. All works ok. However, I’m having an issue
with adding the array of ssh_keys pulled from the data bag to the users
authorized keys file.

include_recipe "slice-ldap"
bag = data_bag(“ssh-keys”)
for item in bag do
user = data_bag_item(‘ssh-keys’, item)
user_name = user[‘id’]
ssh_keys = user[‘ssh_keys’]
execute “create_home_#{user_name}” do
command "su - #{user_name} -c “ls”"
creates "/home/#{user_name}"
notifies :run, “execute[create_ssh_dir_#{user_name}]”, :immediately
end
execute “create_ssh_dir_#{user_name}” do
command "su - #{user_name} -c “mkdir /home/#{user_name}/.ssh”"
notifies :run, “execute[install_public_rsa_#{user_name}]”, :immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute “install_public_rsa_#{user_name}” do
command "su - #{user_name} -c “echo ‘#{k}’ >>
/home/#{user_name}/.ssh/authorized_keys”"
action :nothing
end
end
end

However, I’m having an issue with adding the array of ssh_keys pulled from
the data bag to the users authorized keys file. The loop at the end does
this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:inblock (2 levels) in from_file’

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I’m using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Why not just template the authorized_keys file and write to it directly as
root? You can always set the owner/group/mode/etc of the file to be what
you'd normally expect, but there's no need to use an execute resource and
output redirection to accomplish it.

This is actually something on my to-do list, though I'll probably just use
the standard cookbook and modify it to skip ldap users that aren't present
on a given box.

--
~~ StormeRider ~~

"Every world needs its heroes [...] They inspire us to be better than we
are. And they protect from the darkness that's just around the corner."

(from Smallville Season 6x1: "Zod")

On why I hate the phrase "that's so lame"... http://bit.ly/Ps3uSS

On Mon, Jan 26, 2015 at 2:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

I'm having trouble setting up users authorized keys. A cookbook that runs
earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a data
bag and then for each user running a command as this user. That makes PAM
do all the home directory setup for me. I create the ~/.ssh directory in a
similar fashion, as the user. All works ok. However, I'm having an issue
with adding the array of ssh_keys pulled from the data bag to the users
authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]", :immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled from
the data bag to the users authorized keys file. The loop at the end does
this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Have you tried reloading Ohai after your recipe that sets up LDAP runs? I
would presume Chef doesn't know about your users because Ohai is run before
you have LDAP setup. Reloading Ohai might get the ball rolling and your
users might get discovered.

On Mon, Jan 26, 2015 at 5:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

I'm having trouble setting up users authorized keys. A cookbook that runs
earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.

Morgan,

If I use template, then typical 'owner' and 'group' attributes will not
work.

Doug.

On Mon, Jan 26, 2015 at 2:37 PM, Morgan Blackthorne stormerider@gmail.com
wrote:

Why not just template the authorized_keys file and write to it directly as
root? You can always set the owner/group/mode/etc of the file to be what
you'd normally expect, but there's no need to use an execute resource and
output redirection to accomplish it.

This is actually something on my to-do list, though I'll probably just use
the standard cookbook and modify it to skip ldap users that aren't present
on a given box.

--
~~ StormeRider ~~

"Every world needs its heroes [...] They inspire us to be better than we
are. And they protect from the darkness that's just around the corner."

(from Smallville Season 6x1: "Zod")

On why I hate the phrase "that's so lame"... http://bit.ly/Ps3uSS

On Mon, Jan 26, 2015 at 2:29 PM, Douglas Garstang <doug.garstang@gmail.com

wrote:

I'm having trouble setting up users authorized keys. A cookbook that runs
earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a data
bag and then for each user running a command as this user. That makes PAM
do all the home directory setup for me. I create the ~/.ssh directory in a
similar fashion, as the user. All works ok. However, I'm having an issue
with adding the array of ssh_keys pulled from the data bag to the users
authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled
from the data bag to the users authorized keys file. The loop at the end
does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

Your issue is due to the fact that when you loop through the ssh keys,
you are creating an execute resource with the same name multiple
times, and each one is overwriting the other. Every resource must be
uniquely named, and you would have to notify them all.

If you don't want to use a template as suggested elsewhere (a template
is the best way provided you don't need to support people adding their
own keys), then I would suggest building a variable containing all
keys and writing them in a single execute resource. Something like the
following (untested) code:

execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{ssh_keys.join("\n")}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end

(and don't have the ssh_keys.each_with_index block at all).

On Mon, Jan 26, 2015 at 5:29 PM, Douglas Garstang
doug.garstang@gmail.com wrote:

I'm having trouble setting up users authorized keys. A cookbook that runs
earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a data bag
and then for each user running a command as this user. That makes PAM do all
the home directory setup for me. I create the ~/.ssh directory in a similar
fashion, as the user. All works ok. However, I'm having an issue with adding
the array of ssh_keys pulled from the data bag to the users authorized keys
file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]", :immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled from
the data bag to the users authorized keys file. The loop at the end does
this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is not
there. The log statement shows each key, so I know the loop is iterating
over both. What gives?

Doug

On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I
don't understand, none of that user information is available during
the chef run. I previously posted about this once before. As a result,
I can't simply create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That
makes PAM do all the home directory setup for me. I create the ~/.ssh
directory in a similar fashion, as the user. All works ok. However,
I'm having an issue with adding the array of ssh_keys pulled from the
data bag to the users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled
from the data bag to the users authorized keys file. The loop at the
end does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one
is not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're
only notifying one of those blocks. You could add the index to then
name and then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc.
Similarly executing to su is a huge antipattern, so you can replace the
rest of that.

Sorry to have to repeat myself, but I can't use 'owner' and 'group' on
resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run, the
LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated until
after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io wrote:

On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a data
bag and then for each user running a command as this user. That makes PAM
do all the home directory setup for me. I create the ~/.ssh directory in a
similar fashion, as the user. All works ok. However, I'm having an issue
with adding the array of ssh_keys pulled from the data bag to the users
authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]", :immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled from
the data bag to the users authorized keys file. The loop at the end does
this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any notifications
or subscriptions, you can push new keys out and it'll correctly update,
gets the job done with fewer resources, etc. Similarly executing to su is
a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

I don't believe so, if you are on the node itself, you'd have access to
attributes even before the node has been saved. The situation you describe
would apply to other nodes looking at this nodes data.

This really sounds like an Ohai race condition. In your case the second run
now has LDAP enabled properly so Ohai is able to detect the users. Does
your LDAP recipe restart any services? Are those services restarted delayed
or immediate? If you have any delayed restarts in that recipe immediate
might help here. Without knowing what the recipe its a little hard, but
maybe add a notification on your last resource in your ldap recipe to call
the ohai reload similar to the second example in
ohai Resource.

What I am seeing, (I'm using vagrant), is that on the first chef run, the
LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated until
after the chef run issue?

David,

I'm using the standard LDAP cookbook for Ubuntu. I don't have a lot of
control over how it does restarts. I do have the ohai reload at the end of
my wrapper cookbook, so that should yield the same result as having it
inside the upstream cookbook.

If the users aren't immediately available after the LDAP cookbook has run,
it sounds like a bug with the LDAP cookbook.

Doug.

On Mon, Jan 26, 2015 at 3:47 PM, David Petzel davidpetzel@gmail.com wrote:

I don't believe so, if you are on the node itself, you'd have access to
attributes even before the node has been saved. The situation you describe
would apply to other nodes looking at this nodes data.

This really sounds like an Ohai race condition. In your case the second
run now has LDAP enabled properly so Ohai is able to detect the users. Does
your LDAP recipe restart any services? Are those services restarted delayed
or immediate? If you have any delayed restarts in that recipe immediate
might help here. Without knowing what the recipe its a little hard, but
maybe add a notification on your last resource in your ldap recipe to call
the ohai reload similar to the second example in
ohai Resource.

What I am seeing, (I'm using vagrant), is that on the first chef run, the
LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

Chef and Ohai use the Etc library in Ruby, which in turn uses the standard getpw* and getgr* calls. These are configured by nsswitch.conf. If you go look this up, you'll see that that file is only read once for a given process and there is no universal way to clear the config. Some libcs offer non-standard calls for it, but I doubt any of those are exposed to Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group' on resources. Even thought LDAP is configured, chef isn't able to see the users and groups.

David suggested I reload ohai. I had no idea this was necessary or required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run, the LDAP users are not in in the node structure. However, if I reprovision, (without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that runs earlier in the runlist sets up LDAP. However, due to reasons I don't understand, none of that user information is available during the chef run. I previously posted about this once before. As a result, I can't simply create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a data bag and then for each user running a command as this user. That makes PAM do all the home directory setup for me. I create the ~/.ssh directory in a similar fashion, as the user. All works ok. However, I'm having an issue with adding the array of ssh_keys pulled from the data bag to the users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]", :immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >> /home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled from the data bag to the users authorized keys file. The loop at the end does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the authorized_keys file. Even though I'm using echo and >>, the last one is not there. The log statement shows each key, so I know the loop is iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining multiple resources called execute[install_public_rsa_doug] and the resource collection and the way notifies and subscribes is implemented requires unique names. So you're getting resource cloning and you're only notifying one of those blocks. You could add the index to then name and then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >> /home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any notifications or subscriptions, you can push new keys out and it'll correctly update, gets the job done with fewer resources, etc. Similarly executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

So, it would seem this this is a general chef issue then. It's not an LDAP
issue, or an ohai issue. It's a chef issue.

A workaround for this limitation sure would be nice. Configuring user with
LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

Doug.

On Mon, Jan 26, 2015 at 3:52 PM, Noah Kantrowitz noah@coderanger.net
wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the standard
getpw* and getgr* calls. These are configured by nsswitch.conf. If you go
look this up, you'll see that that file is only read once for a given
process and there is no universal way to clear the config. Some libcs offer
non-standard calls for it, but I doubt any of those are exposed to Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group' on
resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run,
the LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled
from the data bag to the users authorized keys file. The loop at the end
does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

Actually, I think it's time for a script.

On Mon, Jan 26, 2015 at 3:55 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

So, it would seem this this is a general chef issue then. It's not an LDAP
issue, or an ohai issue. It's a chef issue.

A workaround for this limitation sure would be nice. Configuring user with
LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

Doug.

On Mon, Jan 26, 2015 at 3:52 PM, Noah Kantrowitz noah@coderanger.net
wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the
standard getpw* and getgr* calls. These are configured by nsswitch.conf. If
you go look this up, you'll see that that file is only read once for a
given process and there is no universal way to clear the config. Some libcs
offer non-standard calls for it, but I doubt any of those are exposed to
Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group' on
resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run,
the LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled
from the data bag to the users authorized keys file. The loop at the end
does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

Or... something like:

AuthorizedKeysFile /etc/ssh/authorized_keys/%u

in /etc/ssh/sshd_config. The users account doesn't need to exist first, and
it's owned by root and managed by chef, not the user.

Doug.

On Mon, Jan 26, 2015 at 3:56 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Actually, I think it's time for a script.

On Mon, Jan 26, 2015 at 3:55 PM, Douglas Garstang <doug.garstang@gmail.com

wrote:

So, it would seem this this is a general chef issue then. It's not an
LDAP issue, or an ohai issue. It's a chef issue.

A workaround for this limitation sure would be nice. Configuring user
with LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

Doug.

On Mon, Jan 26, 2015 at 3:52 PM, Noah Kantrowitz noah@coderanger.net
wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the
standard getpw* and getgr* calls. These are configured by nsswitch.conf. If
you go look this up, you'll see that that file is only read once for a
given process and there is no universal way to clear the config. Some libcs
offer non-standard calls for it, but I doubt any of those are exposed to
Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group' on
resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run,
the LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]",
:immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled
from the data bag to the users authorized keys file. The loop at the end
does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

Alternately, you could perform the LDAP search yourself and work with the
returned entries.

Rgds,

mgh

On Tue, Jan 27, 2015 at 11:14 AM, Douglas Garstang doug.garstang@gmail.com
wrote:

Or... something like:

AuthorizedKeysFile /etc/ssh/authorized_keys/%u

in /etc/ssh/sshd_config. The users account doesn't need to exist first,
and it's owned by root and managed by chef, not the user.

Doug.

On Mon, Jan 26, 2015 at 3:56 PM, Douglas Garstang <doug.garstang@gmail.com

wrote:

Actually, I think it's time for a script.

On Mon, Jan 26, 2015 at 3:55 PM, Douglas Garstang <
doug.garstang@gmail.com> wrote:

So, it would seem this this is a general chef issue then. It's not an
LDAP issue, or an ohai issue. It's a chef issue.

A workaround for this limitation sure would be nice. Configuring user
with LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

Doug.

On Mon, Jan 26, 2015 at 3:52 PM, Noah Kantrowitz noah@coderanger.net
wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the
standard getpw* and getgr* calls. These are configured by nsswitch.conf. If
you go look this up, you'll see that that file is only read once for a
given process and there is no universal way to clear the config. Some libcs
offer non-standard calls for it, but I doubt any of those are exposed to
Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group'
on resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run,
the LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]",
:immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys
pulled from the data bag to the users authorized keys file. The loop at the
end does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

Hi,

A workaround for this limitation sure would be nice. Configuring user with
LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

As Noah mentioned, this is a limitation of any long-lived process that
tries to make use of the glibc interface for retrieving user
information and NSS. BTM discussed this issue here:

https://tickets.opscode.com/browse/CHEF-3780

and postulated that running nscd and forcing a restart of nscd on any
nsswitch.conf changes might be a viable workaround (based on comments
from the previous glibc maintainer). However, from the rest of this
thread it seems like you found a solution for your particular problem,
but if you run into this issue again you might take a look at nscd.

Hope this helps.

Sincerely,

Steven

Hi Michael.

Is this formerly Spry Michael? Apparently, openssh supports the following:

AuthorizedKeysFile "%h/.ssh/authorized_keys /etc/ssh/%u/authorized_keys"

That's pretty cool because if first searches the standard location, and
then the secondary location. This means I don't have to worry about
applying the new setting before the keys have been deposited (in which case
the keys wouldn't work), and I can add the keys in later. Also don't have
to worry about users at all.

Doug.

On Mon, Jan 26, 2015 at 4:33 PM, Michael Herman mgh@historyhound.com
wrote:

Alternately, you could perform the LDAP search yourself and work with the
returned entries.

Rgds,

mgh

On Tue, Jan 27, 2015 at 11:14 AM, Douglas Garstang <
doug.garstang@gmail.com> wrote:

Or... something like:

AuthorizedKeysFile /etc/ssh/authorized_keys/%u

in /etc/ssh/sshd_config. The users account doesn't need to exist first,
and it's owned by root and managed by chef, not the user.

Doug.

On Mon, Jan 26, 2015 at 3:56 PM, Douglas Garstang <
doug.garstang@gmail.com> wrote:

Actually, I think it's time for a script.

On Mon, Jan 26, 2015 at 3:55 PM, Douglas Garstang <
doug.garstang@gmail.com> wrote:

So, it would seem this this is a general chef issue then. It's not an
LDAP issue, or an ohai issue. It's a chef issue.

A workaround for this limitation sure would be nice. Configuring user
with LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

Doug.

On Mon, Jan 26, 2015 at 3:52 PM, Noah Kantrowitz noah@coderanger.net
wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the
standard getpw* and getgr* calls. These are configured by nsswitch.conf. If
you go look this up, you'll see that that file is only read once for a
given process and there is no universal way to clear the config. Some libcs
offer non-standard calls for it, but I doubt any of those are exposed to
Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group'
on resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef
run, the LDAP users are not in in the node structure. However, if I
reprovision, (without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook
that runs earlier in the runlist sets up LDAP. However, due to reasons I
don't understand, none of that user information is available during the
chef run. I previously posted about this once before. As a result, I can't
simply create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]",
:immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys
pulled from the data bag to the users authorized keys file. The loop at the
end does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to
the authorized_keys file. Even though I'm using echo and >>, the last one
is not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

Uli Drepper's response from 10 years ago is to run nscd:

https://bugzilla.redhat.com/show_bug.cgi?id=132608#c2

Not sure if a process starts before nscd if there's still a race there
or not, but I think every time you hit the nss functions in glibc it
checks the ncsd socket so that it would work.

On 1/26/15 3:52 PM, Noah Kantrowitz wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the standard getpw* and getgr* calls. These are configured by nsswitch.conf. If you go look this up, you'll see that that file is only read once for a given process and there is no universal way to clear the config. Some libcs offer non-standard calls for it, but I doubt any of those are exposed to Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group' on resources. Even thought LDAP is configured, chef isn't able to see the users and groups.

David suggested I reload ohai. I had no idea this was necessary or required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run, the LDAP users are not in in the node structure. However, if I reprovision, (without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that runs earlier in the runlist sets up LDAP. However, due to reasons I don't understand, none of that user information is available during the chef run. I previously posted about this once before. As a result, I can't simply create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a data bag and then for each user running a command as this user. That makes PAM do all the home directory setup for me. I create the ~/.ssh directory in a similar fashion, as the user. All works ok. However, I'm having an issue with adding the array of ssh_keys pulled from the data bag to the users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]", :immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]", :immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >> /home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled from the data bag to the users authorized keys file. The loop at the end does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the authorized_keys file. Even though I'm using echo and >>, the last one is not there. The log statement shows each key, so I know the loop is iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining multiple resources called execute[install_public_rsa_doug] and the resource collection and the way notifies and subscribes is implemented requires unique names. So you're getting resource cloning and you're only notifying one of those blocks. You could add the index to then name and then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >> /home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any notifications or subscriptions, you can push new keys out and it'll correctly update, gets the job done with fewer resources, etc. Similarly executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

I am using nscd. It's functionality, and how it is restarted, is wrapped up
in the upstream LDAP cookbook.

Doug.

On Mon, Jan 26, 2015 at 7:10 PM, Lamont Granquist lamont@chef.io wrote:

Uli Drepper's response from 10 years ago is to run nscd:

132608 – glibc: [RFE] NSS auto-reload nsswitch.conf

Not sure if a process starts before nscd if there's still a race there or
not, but I think every time you hit the nss functions in glibc it checks
the ncsd socket so that it would work.

On 1/26/15 3:52 PM, Noah Kantrowitz wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the
standard getpw* and getgr* calls. These are configured by nsswitch.conf. If
you go look this up, you'll see that that file is only read once for a
given process and there is no universal way to clear the config. Some libcs
offer non-standard calls for it, but I doubt any of those are exposed to
Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group' on

resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run,
the LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]",
:immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys pulled
from the data bag to the users authorized keys file. The loop at the end
does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-
1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo- 1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels)
in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

So I'm actually looking to do this myself, though I want the config to be:

AuthorizedKeysFile "%h/.ssh/authorized_keys /etc/ssh/%u/authorized_keys"

That way they can use manual keys in addition to the ones I'll be having
chef drop in place. However, I'm not currently managing
/etc/ssh/sshd_config. What's the best way to modify just that one line? I'm
a bit uneasy about trying to just cookbook_file that, given how many
different Linux distributions we have (Oracle, Redhat, Debian, Ubuntu,
CentOS, etc).
On Jan 26, 2015 4:15 PM, "Douglas Garstang" doug.garstang@gmail.com wrote:

Or... something like:

AuthorizedKeysFile /etc/ssh/authorized_keys/%u

in /etc/ssh/sshd_config. The users account doesn't need to exist first,
and it's owned by root and managed by chef, not the user.

Doug.

On Mon, Jan 26, 2015 at 3:56 PM, Douglas Garstang <doug.garstang@gmail.com

wrote:

Actually, I think it's time for a script.

On Mon, Jan 26, 2015 at 3:55 PM, Douglas Garstang <
doug.garstang@gmail.com> wrote:

So, it would seem this this is a general chef issue then. It's not an
LDAP issue, or an ohai issue. It's a chef issue.

A workaround for this limitation sure would be nice. Configuring user
with LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

Doug.

On Mon, Jan 26, 2015 at 3:52 PM, Noah Kantrowitz noah@coderanger.net
wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the
standard getpw* and getgr* calls. These are configured by nsswitch.conf. If
you go look this up, you'll see that that file is only read once for a
given process and there is no universal way to clear the config. Some libcs
offer non-standard calls for it, but I doubt any of those are exposed to
Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group'
on resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef run,
the LDAP users are not in in the node structure. However, if I reprovision,
(without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook that
runs earlier in the runlist sets up LDAP. However, due to reasons I don't
understand, none of that user information is available during the chef run.
I previously posted about this once before. As a result, I can't simply
create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]",
:immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys
pulled from the data bag to the users authorized keys file. The loop at the
end does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to the
authorized_keys file. Even though I'm using echo and >>, the last one is
not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

YMMV, but I'd reconsider the approach you're taking--"configuring users
with LDAP" seems like the tail wagging the dog a little. I've had much
better luck using SSSD to act as an authentication system that talks to
LDAP instead. You can store public keys in your LDAP server, then, and SSSD
will do the Right Thing. It's a huge step up over nslcd or ldapd.

I've used it on both CentOS and Ubuntu, with significant success.

Good luck!

-Ed

On Tue, Mar 10, 2015 at 10:15 AM, Morgan Blackthorne stormerider@gmail.com
wrote:

So I'm actually looking to do this myself, though I want the config to be:

AuthorizedKeysFile "%h/.ssh/authorized_keys

/etc/ssh/%u/authorized_keys"

That way they can use manual keys in addition to the ones I'll be having
chef drop in place. However, I'm not currently managing
/etc/ssh/sshd_config. What's the best way to modify just that one line? I'm
a bit uneasy about trying to just cookbook_file that, given how many
different Linux distributions we have (Oracle, Redhat, Debian, Ubuntu,
CentOS, etc).
On Jan 26, 2015 4:15 PM, "Douglas Garstang" doug.garstang@gmail.com
wrote:

Or... something like:

AuthorizedKeysFile /etc/ssh/authorized_keys/%u

in /etc/ssh/sshd_config. The users account doesn't need to exist first,
and it's owned by root and managed by chef, not the user.

Doug.

On Mon, Jan 26, 2015 at 3:56 PM, Douglas Garstang <
doug.garstang@gmail.com> wrote:

Actually, I think it's time for a script.

On Mon, Jan 26, 2015 at 3:55 PM, Douglas Garstang <
doug.garstang@gmail.com> wrote:

So, it would seem this this is a general chef issue then. It's not an
LDAP issue, or an ohai issue. It's a chef issue.

A workaround for this limitation sure would be nice. Configuring user
with LDAP and then being able to create their ssh keys seems like a pretty
standard use case.

Doug.

On Mon, Jan 26, 2015 at 3:52 PM, Noah Kantrowitz noah@coderanger.net
wrote:

Chef and Ohai use the Etc library in Ruby, which in turn uses the
standard getpw* and getgr* calls. These are configured by nsswitch.conf. If
you go look this up, you'll see that that file is only read once for a
given process and there is no universal way to clear the config. Some libcs
offer non-standard calls for it, but I doubt any of those are exposed to
Ruby.

--Noah

On Jan 26, 2015, at 3:29 PM, Douglas Garstang doug.garstang@gmail.com
wrote:

Sorry to have to repeat myself, but I can't use 'owner' and 'group'
on resources. Even thought LDAP is configured, chef isn't able to see the
users and groups.

David suggested I reload ohai. I had no idea this was necessary or
required, but I tried it anyway. I put this at the end of my ldap cookbook.

ohai "reload_passwd" do
plugin "etc"
end
log node['etc']['passwd']

What I am seeing, (I'm using vagrant), is that on the first chef
run, the LDAP users are not in in the node structure. However, if I
reprovision, (without making any changes), then the users ARE there.

In hindsight, isn't this just the typical node not being populated
until after the chef run issue?

Doug.

On Mon, Jan 26, 2015 at 3:22 PM, Lamont Granquist lamont@chef.io
wrote:
On 1/26/15 2:29 PM, Douglas Garstang wrote:

I'm having trouble setting up users authorized keys. A cookbook
that runs earlier in the runlist sets up LDAP. However, due to reasons I
don't understand, none of that user information is available during the
chef run. I previously posted about this once before. As a result, I can't
simply create files and directories and use 'owner' and 'group.

I came up with the below idea. I'm iterating over the ssh keys in a
data bag and then for each user running a command as this user. That makes
PAM do all the home directory setup for me. I create the ~/.ssh directory
in a similar fashion, as the user. All works ok. However, I'm having an
issue with adding the array of ssh_keys pulled from the data bag to the
users authorized keys file.

include_recipe "slice-ldap"
bag = data_bag("ssh-keys")
for item in bag do
user = data_bag_item('ssh-keys', item)
user_name = user['id']
ssh_keys = user['ssh_keys']
execute "create_home_#{user_name}" do
command "su - #{user_name} -c "ls""
creates "/home/#{user_name}"
notifies :run, "execute[create_ssh_dir_#{user_name}]",
:immediately
end
execute "create_ssh_dir_#{user_name}" do
command "su - #{user_name} -c "mkdir /home/#{user_name}/.ssh""
notifies :run, "execute[install_public_rsa_#{user_name}]",
:immediately
creates "/home/#{user_name}/.ssh"
end
ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
action :nothing
end
end
end

However, I'm having an issue with adding the array of ssh_keys
pulled from the data bag to the users authorized keys file. The loop at the
end does this, but chef also gives me this warning:

==> default: [2015-01-26T22:23:47+00:00] WARN: Previous
execute[install_public_rsa_doug]:
/tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in
block (2 levels) in from_file' ==> default: [2015-01-26T22:23:47+00:00] WARN: Current execute[install_public_rsa_doug]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/slice-ssh-keys/recipes/default.rb:38:in block (2 levels) in from_file'

Apart from the warning, only the last ssh keys is being added to
the authorized_keys file. Even though I'm using echo and >>, the last one
is not there. The log statement shows each key, so I know the loop is
iterating over both. What gives?

Doug

Yeah the warning is trying to tell you the problem. You're defining
multiple resources called execute[install_public_rsa_doug] and the
resource collection and the way notifies and subscribes is implemented
requires unique names. So you're getting resource cloning and you're only
notifying one of those blocks. You could add the index to then name and
then subscribe to the previous resources:

ssh_keys.each_with_index do |k, index|
log "k = #{k}"
execute "install_public_rsa_#{user_name}#{index}" do
command "su - #{user_name} -c "echo '#{k}' >>
/home/#{user_name}/.ssh/authorized_keys""
subscribes :run, "execute[#{create_ssh_dir
#{user_name}]"
subscribes :run, "execute[#{create_home_#{user_name}]"
action :nothing
end
end

You'll be way better off just doing this though:

file "/home/#{user_name}" do
owner user_name
group user_name # or "users" or whatever
mode "0600"
end

file "/home/#{user_name}/.ssh" do
owner user_name
group user_name
mode "0600"
end

file "/home/#{user_name}/.ssh/authorized_keys" do
owner user_name
group user_name
mode "0600"
content ssh_keys.join("\n")
end

That's idempotent, you don't need the action :nothing or any
notifications or subscriptions, you can push new keys out and it'll
correctly update, gets the job done with fewer resources, etc. Similarly
executing to su is a huge antipattern, so you can replace the rest of that.

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627

--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: doug.garstang@gmail.com
Cell: +1-805-340-5627