Puppet: Set the User's SSH Key

This is the third in a series of posts I'm making detailing my setting up a Puppet master/slave pair of servers on Linode. If you haven't seen them yet, go check out my first and second posts about my Puppet servers.

Where I Left Off

At the end of the second post in the series, I had a Linode running Puppet, had Ubuntu Linux installed on it, and had created a User named mike. I had also set mike's password so that I could login as mike on the slave node.

Here's how the mike user was configured at the end of the last post:

user { "mike":
    ensure     => present,
    gid        => 'mike',
    groups     => [ 'sudo', 'users' ],
    shell      => '/usr/bin/fish',
    home       => '/home/mike',
    managehome => true,
    password   => '$1$qH8newGR$4nApEG7NQHqLHYNLIEZlx0',

SSH Keys

SSH Keys are a more secure way to login to your servers, and it also doesn't require you to either remember or type your password every single time.

Creating a Key Pair

Following the article, on my Mac laptop, I created an SSH key for use in this blog post:

mvitale@mavelous ~/.ssh> ssh-keygen -f mike-blog
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in mike-blog.
Your public key has been saved in mike-blog.pub.
The key fingerprint is:
02:57:66:95:a7:4d:0a:c1:9d:42:da:ce:4b:b4:a3:dc mvitale@mavelous.local
The key's randomart image is:
+--[ RSA 2048]----+
|       o*+.o     |
|       *+ + o    |
|    . o oo *     |
|     o + .o .    |
|      . S        |
|     . = o       |
|      o E        |
|                 |
|                 |

Note that if you don't currently have an SSH key, you can leave off the -f mike-blog part. That just sets the filename that will be used by the SSH key that it generates. Since I already had a key pair and I didn't want to use it for this post, I created another one with a distinct name.

Now, looking at my ~/.ssh directory on my laptop:

mvitale@mavelous ~/.ssh> ls
total 72
-rw-------  1 mvitale  staff   225 May 28  2014 authorized_keys2
-rw-r--r--  1 mvitale  staff    38 Feb 20 12:00 config
-rw-------  1 mvitale  staff  1675 May 28  2014 id_rsa
-rw-------  1 mvitale  staff   404 May 29  2014 id_rsa.pub
-rw-r--r--  1 mvitale  staff  8766 Jun  4 07:16 known_hosts
-rw-------  1 mvitale  staff  1675 Jun  8 22:09 mike-blog
-rw-r--r--  1 mvitale  staff   404 Jun  8 22:09 mike-blog.pub

Notice that two files were created: mike-blog and mike-blog.pub. The first is the Private Key, and the second is the Public Key. (If you need a refresher on what that means, check out the Wikipedia page on Public-Key Cryptography.) I'm now ready to move on to configuring this inside Puppet.

Enter Puppet

If I were to login to my user on my puppetslave node and check my home directory, I'd find it pretty bare:

mike@puppetslave ~> ls -laF
total 28
drwxr-xr-x 4 mike mike 4096 Jun  4 06:51 ./
drwxr-xr-x 3 root root 4096 Feb 28 13:13 ../
-rw-r--r-- 1 mike mike  220 Feb 28 13:13 .bash_logout
-rw-r--r-- 1 mike mike 3637 Feb 28 13:13 .bashrc
drwx------ 2 mike mike 4096 Jun  4 06:51 .cache/
drwx------ 3 mike mike 4096 Jun  4 06:51 .config/
-rw-r--r-- 1 mike mike  675 Feb 28 13:13 .profile

SSH Keys need to be stored in the ~/.ssh/authorized_keys2 file. That file needs to have 600 permissions, and the ~/.ssh directory must have 700 permissions. Anything else, and your SSH Keys won't work.

In order to accomplish this, I added the following to my /etc/manifest/site.pp file on my Puppet master node:

    file { "/home/mike/.ssh":
            ensure => 'directory',
            owner  => 'mike',
            group  => 'mike',
            mode   => '0700',

    file { "/home/mike/.ssh/authorized_keys2":
            ensure  => 'present',
            owner   => 'mike',
            group   => 'mike',
            mode    => '0600',
            content => 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYYZ4Rr0RwagRxoc0IINCW+rN7WW/SdkVUUmYnPSWtA/GevM+Z4qizPRiJ4Lb/KTjQQ8Qu0eqlYRU6vAv+O5ewANzZC0Hl9tuclM0Hkzyh/BkiQQvmC9yEgwjJjPhX61tDryW7InHhqNgGP+OqjiJKSUB8sIQ+X82j2opa2ktt5ct9TomDEBvRTz0E4HjIbl0JDuRa+QlGbCGRiA4H+wkk7r7GUqp1fyVlyrH44Qs0k10KzntUj7vnXOI/FFKq65iwK/YbRWeG127neHCVdR0CxmkdNx7Cba+RGA0KfG0LDBBCoGCzST6lgZEbCHhy5CGxrjusUMBOMMiVrYOCHecR mvitale@mavelous.local',

Then, as last time, I ran Puppet manually on the slave node so that the configuration I just set in site.pp would be applied:

[root@puppetslave ~]$ puppet agent --test
Info: Retrieving plugin
Info: Caching catalog for puppetslave.mavelo.us
Info: Applying configuration version '1433820752'
Notice: /Stage[main]/Main/Node[default]/File[/home/mike/.ssh]/ensure: created
Notice: /Stage[main]/Main/Node[default]/File[/home/mike/.ssh/authorized_keys2]/ensure: created
Notice: Finished catalog run in 0.10 seconds

No Password Required

After that, it was simply a matter of issuing an ssh command from my Mac laptop (and making sure to point it to use the correct SSH key on the laptop) and I was able to login, no password required.

mvitale@mavelous ~/.ssh> ssh -i mike-blog mike@puppetslave.mavelo.us
Welcome to Ubuntu 14.04.2 LTS (GNU/Linux 4.0.4-x86_64-linode57 x86_64)

 * Documentation:  https://help.ubuntu.com/

63 packages can be updated.
24 updates are security updates.

Last login: Mon Jun  8 22:33:24 2015 from
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
mike@puppetslave ~> 


This is about what I wanted to accomplish with my user on my Puppet slave node. There's still much to explore. I'm not sure where I'm going next with this, as I have much to learn and many different directions I could head in. Watch this space, and please leave comments below!