This time we're going to lock the server down a bit with Puppet. Now that we have our own user, let's force login using a public key we'll create for the user.
Eventually I also want to create a self signed certificate for the user to use with their public key to access resources via HTTPS with client certificates wrap the whole certificate up in a pkcs12 file and email it to them. I won't get into that yet.
I was going to write the framework myself, even had a skeleton all laid out - I'd decided on two classes, the keystore which would handle creating, storing and revoking keys and later certificates and a user class for creating users.
-
create <user> creates a new user with the given username.
-
clientkey <user> [filename] installs the key for a given user, optionally set a filename. I already have some keys
-
serverkey <user> [login_as] installs the key into the authorized_keys allowing users to login to this server. Defaults to logging in as the same user as the key 'owner' if the. I also need to use my key to login as another user, the git and svn users for example.
Then I found the ssh::auth from the puppet wiki. it's released under the GPL, while everything else I write is Apache 2 compatible - if that's a problem you may want to stop here and look for another solution. If you find one that's Apache 2 compatible, I'd love to know about it. For what I'm doing it doesn't really matter, I went with my skeleton package as a thin wrapper around it and downloaded the module into my users package.
# wget http://projects.reductivelabs.com/attachments/download/935/auth.pp -O ./modules/user/manifests/auth.pp
The first thing I did was create a new keystore.pp file, the ssh::auth package made that pretty easy:
modules/user/manifests/keystore.pp
class user::keystore {
include ssh::auth::keymaster
}
Then I needed to do was create a keystore. The keystore is just the host you nominate to control all your client and server keys. To do that in nodes.pp I properly named my only node and stopped using the default and added a couple of new includes.
manifests/nodes.pp
node build {
include sudo, user, ssh::auth, user::keystore
}
Run puppet and you should end up with a directory
/var/lib/keys
ready to store keys.
# puppet -v --modulepath=/etc/puppet/modules /etc/puppet/manifests/site.pp
I decided I'd update my user package by removing some files and putting the user class into the init.pp file. I had too many files in there that just didn't seem to be doing anything.
# rm modules/user/manifests/virtual.pp
# rm modules/user/manifests/unixadmins.pp
Then I added a create method in the user class in my init.pp file:
modules/users/manifests/init.pp
import "*"
class user {
define create {
@user { "$title":
ensure => "present",
gid => "$title",
home => "/home/$title",
shell => "/bin/bash",
managehome => true,
require => [Group["$title"]],
}
@file { "/home/$title":
ensure => "directory",
mode => 700,
owner => "$title",
group => "$title",
}
@file { "/home/$title/.ssh":
ensure => "directory",
mode => 600,
owner => "$title",
group => "$title",
}
@group { "$title":
ensure => "present",
}
realize User[$title]
realize Group[$title]
realize File["/home/$title"]
realize File["/home/$title/.ssh"]
ssh::auth::key{"$title":}
}
define client_key ($ensure = "", $filename = "") {
ssh::auth::client{"$title": ensure=>$ensure, filename=>$filename}
}
define server_key ($ensure = "", $user = "") {
ssh::auth::server{"$title": ensure=>$ensure, user=>$user}
}
}
This code defines a new method called create, and realises all the required resources, finally it generates a new key for the user.
Now we need to update our node to create ourselves a user using this new method
manifests/nodes.pp
node my-server {
include sudo, ssh::auth, ssh::auth::keymaster, user
user::create{"andrewmccall":}
user::client_key{"andrewmccall":}
user::server_key{"andrewmccall":}
}
The last step is to copy the private and public key down to a machine.
It's important that you test ssh logins to this host using the new keys. Otherwise you risk locking yourself out for good!
I think that's probably a good place for me to call it a night - tomorrow I'll be locking down sshd so that only users with keys can login.