Managing SSH Authorized Keys with Puppet

In this post, I’ll show you how I extended my solution for managing user accounts with Puppet to include managing SSH authorized keys. With this solution in place, user accounts managed through Puppet can also include their SSH public key, and that public key will automatically be installed on hosts where the account is realized. All in all, I think it’s a pretty cool solution.

Just to refresh your memory, here’s the original Puppet manifest code I posted in the original article; this code uses define-based virtual user resources that you then realize on a per-host basis.

(If the code block showing the Puppet code isn’t appearing above, click here.)

Since I posted this original code, I’ve made a few changes. I switched some of the hard-coded values to parameters (stored in a separate subclass), and I made a few stylistic/syntactic changes based on running the code through puppet-lint. But, by and large, this is still quite similar to the code I’m running right now.

Here’s the code after I modified it to include managing SSH authorized keys for user accounts:

(Can’t see the code block? Click here.)

Let’s walk through the changes between the two snippets of code:

  • Two new parameters are added, $sshkeytype and $sshkey. These parameters hold, quite naturally, the SSH key type and the SSH key itself.
  • Several values are parameterized, pulling values from the accounts::params manifest.
  • You can note a number of stylistic and syntactical changes.
  • The accounts::virtual class now includes a stanza using the built-in ssh_authorized_key resource type. This is the real heart of the changes—by adding this to the virtual user resource, it makes sure that when users are realized, their SSH public keys are added to the host.

With this code in place, you’d then define a user like this:

(Click here if the code block doesn’t appear above.)

The requirement for Class[‘accounts::config'] is to ensure that various configuration tasks are finished before the user account is defined; I discussed this in more detail in this post on Puppet, user accounts, and configuration files. Now, when I realize a virtual user resource, Puppet will also ensure that the user’s SSH public key is automatically added to the user’s .ssh/authorized_keys file on that host. Pretty sweet, eh? Further, if the key ever changes, you need only change it on the Puppet server itself, and on the next Puppet agent run the hosts will update themselves.

I freely admit that I’m not a Puppet expert, so there might be better/faster/more efficient ways of doing this. If you are a Puppet expert, please feel free to weigh in below in the comments. I welcome all courteous comments!

Tags: , , ,

  1. mandm’s avatar

    THanks for writing such a nice article, i have used the previous version of this package, but now i wanted to use this new package for ssh key copy across all the servers
    and when i try to update my virtual.pp and init.pp files and i run the puppet apply on client i get this error

    Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find class accounts::params for server-1 on node server-1

    only to realize i donot have a params.pp and what would be the values in it?
    did i miss it in this document?

  2. slowe’s avatar

    Mandm, you didn’t miss it, as I haven’t published any of its contents. I’ll try to see if I can get this stuff pushed up to GitHub, but I don’t know how quickly I might be able to do that. In the meantime, you can probably reverse-engineer the references to params.pp and remove them.

  3. David’s avatar

    Are you planning on a post about the accounts::params functionality? I find your puppet blogs to be quite helpful.

  4. Dimitrios’s avatar

    I think you have something wrong. You forgot to require the home/.ssh/ folfer for the ssh_authorized_key

    It should be:

    if ($sshkey != ” and $sshkeytype != ”) {
    ssh_authorized_key {$title:
    ensure => present,
    name => $title,
    user => $title,
    type => $sshkeytype,
    key => $sshkey,
    require => File["${homepath}/${title}/.ssh"]

  5. slowe’s avatar

    Dimitrios, the .ssh directory was already created elsewhere in another module. Of course, you couldn’t know that, so thanks for pointing that out for other readers!

  6. Mike’s avatar

    Very good article on setting up keys for remote access via SSH. This is a very good tutorial I followed some time ago when I was first starting out. It’s short and concise:

  7. Anthony’s avatar

    Perfect. I just got the idea from yours on how to do ssh key since I have my own user set up. I didnt know puppet had built in ssh_authorized_key. Worked great.

  8. suresh’s avatar

    This code is working perfect for added keys in authorized file.
    But it is overwriting the existing keys, is it possible to append?

  9. slowe’s avatar

    Suresh, you should be able to add keys as well as overwriting existing keys. It will all be in how you write the manifest and declare the resources.


Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>