12

I'm using puppet to distribute SSH keys, like so:

ssh_authorized_key { "[email protected]":
   ensure => present,
   key => 'xxxx',
   type => 'ssh-rsa',
   user => 'deploy',
}

The ~/.ssh/authorized_keys file ends up containing a mix of keys from multiple classes, which is the desired result. However, if a key is manually added to $HOME/.ssh/authorized_keys, Puppet will leave it in place. Is there a way to always remove any key that has not been explicitly defined in a manifest?

I have puppet version 2.7.1.

1
  • I was thinking about using exported resources to get a copy of all my authorized_keys files into a central location. Then I could run scripts to find unusual keys, and either add them to puppet or add a resource to remove them.
    – Zoredache
    Sep 27, 2011 at 19:58

4 Answers 4

4

Starting with Puppet 3.6 it is now possible to purge unmanaged SSH authorized keys via the user type. For example,

user { 'nick':
  ensure         => present,
  purge_ssh_keys => true,
}
0
13

Instead of using ssh_authorized_key resources, I decided to define an authorized_keys resource, which takes a list of all SSH keys for a single user. The define looks like this:

define authorized_keys ($sshkeys, $ensure = "present", $home = '') {
    # This line allows default homedir based on $title variable.
    # If $home is empty, the default is used.
    $homedir = $home ? {'' => "/home/${title}", default => $home}
    file {
        "${homedir}/.ssh":
            ensure  => "directory",
            owner   => $title,
            group   => $title,
            mode    => 700,
            require => User[$title];
        "${homedir}/.ssh/authorized_keys":
            ensure  => $ensure,
            owner   => $ensure ? {'present' => $title, default => undef },
            group   => $ensure ? {'present' => $title, default => undef },
            mode    => 600,
            require => File["${homedir}/.ssh"],
            content => template("authorized_keys.erb");
    }
}

$ssh_keys parameter takes all necessary keys as a list. The authorized_keys.erb template looks like this:

# NOTICE: This file is autogenerated by Puppet and should not be modified
<% sshkeys.each do |key| -%>
<%= key %>
<% end -%>

Usage

user {'mikko':
    ...
}
authorized_keys {'mikko':
    sshkeys => [
        'ssh-rsa XXXXXXYYYYYYYYYZZZZZZZZZ [email protected]',
        'ssh-rsa XXXXXXZZZZZZZZZHHHHHHHHH [email protected]',
    ],
}

Adding SSH keys conditionally (for example in different classes) is also easy, thanks to Puppet's +> operator:

Authorized_keys <| title == 'mikko' |> {
    sshkeys +> 'ssh-rsa ASDFASDFASDFASDF [email protected]'
}

With this method, the user will never have keys that are not explicitly specified in the Puppet configuration. The key string is used in authorized_keys just as it is, so adding options and restrictions is trivial.

I would be happy to hear if others have used this method successfully!

3

You should be able to do this using the resources metatype. E.G.

resources { 'ssh_authorized_key': noop => true, purge => true, }

Setting noop => true, prevents the removal from taking place. Instead, puppet will report what would be removed. If it is what you want, remove the noop statement.

The ideal syntax for performing operations on unmanaged resources is under discussion.

EDIT: As mentioned in the comments, this answer does not work.

4
  • This sound like just what I'm looking for. When I add this line, puppet produces this error: puppet-agent[9895]: (/Stage[main]//Resources[ssh_authorized_key]) Failed to generate additional resources using 'generate': Attribute 'user' or 'target' is mandatory. I tried adding a user, and then it says Could not retrieve catalog from remote server: Error 400 on SERVER: Invalid parameter user . Any ideas?
    – Dylan Tack
    Sep 28, 2011 at 16:00
  • I'm not sure. It's probably worth asking on groups.google.com/group/puppet-users
    – sciurus
    Sep 28, 2011 at 18:28
  • 1
    I'm really unclear why this is the accepted answer: as per Puppet Labs, this doesn't work and hasn't: projects.puppetlabs.com/issues/1917 . OP, did it work for you?
    – Bill Weiss
    Aug 29, 2012 at 20:27
  • 1
    No, I didn't try it, I just expected it to behave like it did for other resources (e.g. hosts, nagios types). Looks like you're right and it does not work for ssh keys yet- projects.puppetlabs.com/issues/1581
    – sciurus
    Aug 30, 2012 at 21:09
1

On Puppet Forge a module has been published under the Apache License, Version 2.0 that offers this ability.

It relies on Puppet concat instead of templates though.

https://github.com/nightfly19/puppet-ssh_keys/tree/master/manifests

Instead of passing an array of keys as a parameter you define separate entries for each key.

Different approach from Mikko's, but same net result.

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .