From 821be9435faf182d011931e6dfe6f30ba014fa23 Mon Sep 17 00:00:00 2001 From: Michael Scherer Date: Sun, 9 Jan 2011 11:15:12 +0000 Subject: move ssh::auth module to external as this is a external module ( so we can more easily keep track of it ) --- external/ssh/manifests/auth.pp | 336 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 external/ssh/manifests/auth.pp (limited to 'external') diff --git a/external/ssh/manifests/auth.pp b/external/ssh/manifests/auth.pp new file mode 100644 index 00000000..08570add --- /dev/null +++ b/external/ssh/manifests/auth.pp @@ -0,0 +1,336 @@ +# ========= +# ssh::auth +# ========= +# +# The latest official release and documentation for ssh::auth can always +# be found at http://reductivelabs.com/trac/puppet/wiki/Recipes/ModuleSSHAuth . +# +# Version: 0.3.2 +# Release date: 2009-12-29 + +class ssh::auth { + +$keymaster_storage = "/var/lib/keys" + +Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" } +Notify { withpath => false } + + +########################################################################## + + +# ssh::auth::key + +# Declare keys. The approach here is just to define a bunch of +# virtual resources, representing key files on the keymaster, client, +# and server. The virtual keys are then realized by +# ssh::auth::{keymaster,client,server}, respectively. The reason for +# doing things that way is that it makes ssh::auth::key into a "one +# stop shop" where users can declare their keys with all of their +# parameters, whether those parameters apply to the keymaster, server, +# or client. The real work of creating, installing, and removing keys +# is done in the private definitions called by the virtual resources: +# ssh_auth_key_{master,server,client}. + +define key ($ensure = "present", $filename = "", $force = false, $group = "puppet", $home = "", $keytype = "rsa", $length = 2048, $maxdays = "", $mindate = "", $options = "", $user = "") { + + ssh_auth_key_namecheck { "${title}-title": parm => "title", value => $title } + + # apply defaults + $_filename = $filename ? { "" => "id_${keytype}", default => $filename } + $_length = $keytype ? { "rsa" => $length, "dsa" => 1024 } + $_user = $user ? { + "" => regsubst($title, '^([^@]*)@?.*$', '\1'), + default => $user, + } + $_home = $home ? { "" => "/home/$_user", default => $home } + + ssh_auth_key_namecheck { "${title}-filename": parm => "filename", value => $_filename } + + @ssh_auth_key_master { $title: + ensure => $ensure, + force => $force, + keytype => $keytype, + length => $_length, + maxdays => $maxdays, + mindate => $mindate, + } + @ssh_auth_key_client { $title: + ensure => $ensure, + filename => $_filename, + group => $group, + home => $_home, + user => $_user, + } + @ssh_auth_key_server { $title: + ensure => $ensure, + group => $group, + home => $_home, + options => $options, + user => $_user, + } +} + + +########################################################################## + + +# ssh::auth::keymaster +# +# Keymaster host: +# Create key storage; create, regenerate, and remove key pairs + +class keymaster { + + # Set up key storage + + file { $ssh::auth::keymaster_storage: + ensure => directory, + owner => puppet, + group => puppet, + mode => 644, + } + + # Realize all virtual master keys + Ssh_auth_key_master <| |> + +} # class keymaster + + +########################################################################## + + +# ssh::auth::client +# +# Install generated key pairs onto clients + +define client ($ensure = "", $filename = "", $group = "", $home = "", $user = "") { + + # Realize the virtual client keys. + # Override the defaults set in ssh::auth::key, as needed. + if $ensure { Ssh_auth_key_client <| title == $title |> { ensure => $ensure } } + if $filename { Ssh_auth_key_client <| title == $title |> { filename => $filename } } + if $group { Ssh_auth_key_client <| title == $title |> { group => $group } } + + if $user { Ssh_auth_key_client <| title == $title |> { user => $user, home => "/home/$user" } } + if $home { Ssh_auth_key_client <| title == $title |> { home => $home } } + + realize Ssh_auth_key_client[$title] + +} # define client + + +########################################################################## + + +# ssh::auth::server +# +# Install public keys onto clients + +define server ($ensure = "", $group = "", $home = "", $options = "", $user = "") { + + # Realize the virtual server keys. + # Override the defaults set in ssh::auth::key, as needed. + if $ensure { Ssh_auth_key_server <| title == $title |> { ensure => $ensure } } + if $group { Ssh_auth_key_server <| title == $title |> { group => $group } } + if $options { Ssh_auth_key_server <| title == $title |> { options => $options } } + + if $user { Ssh_auth_key_server <| title == $title |> { user => $user, home => "/home/$user" } } + if $home { Ssh_auth_key_server <| title == $title |> { home => $home } } + + realize Ssh_auth_key_server[$title] + +} # define server + +} # class ssh::auth + + +########################################################################## + + +# ssh_auth_key_master +# +# Create/regenerate/remove a key pair on the keymaster. +# This definition is private, i.e. it is not intended to be called directly by users. +# ssh::auth::key calls it to create virtual keys, which are realized in ssh::auth::keymaster. + +define ssh_auth_key_master ($ensure, $force, $keytype, $length, $maxdays, $mindate) { + + Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" } + File { + owner => puppet, + group => puppet, + mode => 600, + } + + $keydir = "${ssh::auth::keymaster_storage}/${title}" + $keyfile = "${keydir}/key" + + file { + "$keydir": + ensure => directory, + mode => 644; + "$keyfile": + ensure => $ensure; + "${keyfile}.pub": + ensure => $ensure, + mode => 644; + } + + if $ensure == "present" { + + # Remove the existing key pair, if + # * $force is true, or + # * $maxdays or $mindate criteria aren't met, or + # * $keytype or $length have changed + + $keycontent = file("${keyfile}.pub", "/dev/null") + if $keycontent { + + if $force { + $reason = "force=true" + } + if !$reason and $mindate and generate("/usr/bin/find", $keyfile, "!", "-newermt", "${mindate}") { + $reason = "created before ${mindate}" + } + if !$reason and $maxdays and generate("/usr/bin/find", $keyfile, "-mtime", "+${maxdays}") { + $reason = "older than ${maxdays} days" + } + if !$reason and $keycontent =~ /^ssh-... [^ ]+ (...) (\d+)$/ { + if $keytype != $1 { $reason = "keytype changed: $1 -> $keytype" } + else { if $length != $2 { $reason = "length changed: $2 -> $length" } } + } + if $reason { + exec { "Revoke previous key ${title}: ${reason}": + command => "rm $keyfile ${keyfile}.pub", + before => Exec["Create key $title: $keytype, $length bits"], + } + } + } + + # Create the key pair. + # We "repurpose" the comment field in public keys on the keymaster to + # store data about the key, i.e. $keytype and $length. This avoids + # having to rerun ssh-keygen -l on every key at every run to determine + # the key length. + exec { "Create key $title: $keytype, $length bits": + command => "ssh-keygen -t ${keytype} -b ${length} -f ${keyfile} -C \"${keytype} ${length}\" -N \"\"", + user => "puppet", + group => "puppet", + creates => $keyfile, + require => File[$keydir], + before => File[$keyfile, "${keyfile}.pub"], + } + + } # if $ensure == "present" + +} # define ssh_auth_key_master + + +########################################################################## + + +# ssh_auth_key_client +# +# Install a key pair into a user's account. +# This definition is private, i.e. it is not intended to be called directly by users. + +define ssh_auth_key_client ($ensure, $filename, $group, $home, $user) { + + File { + owner => $user, + group => $group, + mode => 600, + require => [ User[$user], File[$home]], + } + + $key_src_file = "${ssh::auth::keymaster_storage}/${title}/key" # on the keymaster + $key_tgt_file = "${home}/.ssh/${filename}" # on the client + + $key_src_content_pub = file("${key_src_file}.pub", "/dev/null") + if $ensure == "absent" or $key_src_content_pub =~ /^(ssh-...) ([^ ]+)/ { + $keytype = $1 + $modulus = $2 + file { + $key_tgt_file: + ensure => $ensure, + content => file($key_src_file, "/dev/null"); + "${key_tgt_file}.pub": + ensure => $ensure, + content => "$keytype $modulus $title\n", + mode => 644; + } + } else { + notify { "Private key file $key_src_file for key $title not found on keymaster; skipping ensure => present": } + } + +} # define ssh_auth_key_client + + +########################################################################## + + +# ssh_auth_key_server +# +# Install a public key into a server user's authorized_keys(5) file. +# This definition is private, i.e. it is not intended to be called directly by users. + +define ssh_auth_key_server ($ensure, $group, $home, $options, $user) { + + # on the keymaster: + $key_src_dir = "${ssh::auth::keymaster_storage}/${title}" + $key_src_file = "${key_src_dir}/key.pub" + # on the server: + $key_tgt_file = "${home}/.ssh/authorized_keys" + + File { + owner => $user, + group => $group, + require => User[$user], + mode => 600, + } + Ssh_authorized_key { + user => $user, + target => $key_tgt_file, + } + + if $ensure == "absent" { + ssh_authorized_key { $title: ensure => "absent" } + } + else { + $key_src_content = file($key_src_file, "/dev/null") + if ! $key_src_content { + notify { "Public key file $key_src_file for key $title not found on keymaster; skipping ensure => present": } + } else { if $ensure == "present" and $key_src_content !~ /^(ssh-...) ([^ ]*)/ { + err("Can't parse public key file $key_src_file") + notify { "Can't parse public key file $key_src_file for key $title on the keymaster: skipping ensure => $ensure": } + } else { + $keytype = $1 + $modulus = $2 + ssh_authorized_key { $title: + ensure => "present", + type => $keytype, + key => $modulus, + options => $options ? { "" => undef, default => $options }, + } + }} # if ... else ... else + } # if ... else + +} # define ssh_auth_key_server + + +########################################################################## + + +# ssh_auth_key_namecheck +# +# Check a name (e.g. key title or filename) for the allowed form + +define ssh_auth_key_namecheck ($parm, $value) { + if $value !~ /^[A-Za-z0-9]/ { + fail("ssh::auth::key: $parm '$value' not allowed: must begin with a letter or digit") + } + if $value !~ /^[A-Za-z0-9_.:@-]+$/ { + fail("ssh::auth::key: $parm '$value' not allowed: may only contain the characters A-Za-z0-9_.:@-") + } +} # define namecheck -- cgit v1.2.1