Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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

ssh_authorized_key { "alice@foo.com":
   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.

share|improve this question
    
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 '11 at 19:58
add comment

3 Answers

up vote 3 down vote accepted

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.

share|improve this answer
    
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 '11 at 16:00
    
I'm not sure. It's probably worth asking on groups.google.com/group/puppet-users –  sciurus Sep 28 '11 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 '12 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 '12 at 21:09
add comment

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 mikko@domain.tld',
        'ssh-rsa XXXXXXZZZZZZZZZHHHHHHHHH mikko@other-host.tld',
    ],
}

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 mikko@somewhere-else.tld'
}

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!

share|improve this answer
add comment

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.

share|improve this answer
    
forge.puppetlabs.com/nightfly/ssh_keys is the Puppet Forge link. –  Rodney Feb 24 at 19:24
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.