diff options
Diffstat (limited to 'external/sshkeys/manifests')
-rw-r--r-- | external/sshkeys/manifests/create_key.pp | 29 | ||||
-rw-r--r-- | external/sshkeys/manifests/init.pp | 2 | ||||
-rw-r--r-- | external/sshkeys/manifests/keymaster.pp | 13 | ||||
-rw-r--r-- | external/sshkeys/manifests/namecheck.pp | 12 | ||||
-rw-r--r-- | external/sshkeys/manifests/set_authorized_keys.pp | 58 | ||||
-rw-r--r-- | external/sshkeys/manifests/set_client_key_pair.pp | 39 | ||||
-rw-r--r-- | external/sshkeys/manifests/setup_key_master.pp | 87 | ||||
-rw-r--r-- | external/sshkeys/manifests/var.pp | 4 |
8 files changed, 244 insertions, 0 deletions
diff --git a/external/sshkeys/manifests/create_key.pp b/external/sshkeys/manifests/create_key.pp new file mode 100644 index 00000000..8d40c038 --- /dev/null +++ b/external/sshkeys/manifests/create_key.pp @@ -0,0 +1,29 @@ +define sshkeys::create_key ( + $ensure = "present", + $filename = "", + $force = false, + $keytype = "rsa", + $length = 2048, + $maxdays = "", + $mindate = "", +) { + sshkeys::namecheck { "${title}-title": parm => "title", value => $title } + + # apply defaults + $_filename = $filename ? { "" => "id_${keytype}", default => $filename } + $_length = $keytype ? { "rsa" => $length, "dsa" => 1024 } + + sshkeys::namecheck { "${title}-filename": + parm => "filename", + value => $_filename, + } + + @sshkeys::setup_key_master { $title: + ensure => $ensure, + force => $force, + keytype => $keytype, + length => $_length, + maxdays => $maxdays, + mindate => $mindate, + } +} diff --git a/external/sshkeys/manifests/init.pp b/external/sshkeys/manifests/init.pp new file mode 100644 index 00000000..bcec1847 --- /dev/null +++ b/external/sshkeys/manifests/init.pp @@ -0,0 +1,2 @@ +class sshkeys {
+}
diff --git a/external/sshkeys/manifests/keymaster.pp b/external/sshkeys/manifests/keymaster.pp new file mode 100644 index 00000000..c5013b13 --- /dev/null +++ b/external/sshkeys/manifests/keymaster.pp @@ -0,0 +1,13 @@ +# Keymaster host: +# Create key storage; create, regenerate, and remove key pairs +class sshkeys::keymaster { + include sshkeys::var + file { $sshkeys::var::keymaster_storage: + ensure => directory, + owner => puppet, + group => puppet, + mode => 644, + } + # Realize all virtual master keys + Sshkeys::Setup_key_master <| |> +} diff --git a/external/sshkeys/manifests/namecheck.pp b/external/sshkeys/manifests/namecheck.pp new file mode 100644 index 00000000..ad3d1c70 --- /dev/null +++ b/external/sshkeys/manifests/namecheck.pp @@ -0,0 +1,12 @@ +# Check a name (e.g. key title or filename) for the allowed form +define sshkeys::namecheck ( + $parm, + $value +) { + if $value !~ /^[A-Za-z0-9]/ { + fail("sshkeys::key: $parm '$value' not allowed: must begin with a letter or digit") + } + if $value !~ /^[A-Za-z0-9_.:@-]+$/ { + fail("sshkeys::key: $parm '$value' not allowed: may only contain the characters A-Za-z0-9_.:@-") + } +} diff --git a/external/sshkeys/manifests/set_authorized_keys.pp b/external/sshkeys/manifests/set_authorized_keys.pp new file mode 100644 index 00000000..6bbbb1b5 --- /dev/null +++ b/external/sshkeys/manifests/set_authorized_keys.pp @@ -0,0 +1,58 @@ +# Install a public key into a server user's authorized_keys(5) file. +define sshkeys::set_authorized_keys ( + $keyname = '', + $ensure = 'present', + $group = '', + $home = '', + $options = '', + $user +) { + include sshkeys::var + $_keyname = $keyname ? { '' => $title, default => $keyname } + $_home = $home ? { "" => "/home/${user}", default => $home } + # on the keymaster: + $key_src_dir = "${sshkeys::var::keymaster_storage}/${_keyname}" + $key_src_file = "${key_src_dir}/key.pub" + # on the server: + $key_tgt_file = "${_home}/.ssh/authorized_keys" + + File { + owner => $user, + group => $group ? { "" => $user, default => $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 $_keyname 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 $_keyname 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 }, + } + } + } + } +} diff --git a/external/sshkeys/manifests/set_client_key_pair.pp b/external/sshkeys/manifests/set_client_key_pair.pp new file mode 100644 index 00000000..4cb4281e --- /dev/null +++ b/external/sshkeys/manifests/set_client_key_pair.pp @@ -0,0 +1,39 @@ +# Install a key pair into a user's account. +define sshkeys::set_client_key_pair ( + $keyname = '', + $ensure = 'present', + $filename = 'id_rsa', + $group = '', + $home = '', + $user +) { + include sshkeys::var + File { + owner => $user, + group => $group ? { '' => $user, default => $group }, + mode => 600, + require => [ User[$user], File[$home]], + } + + $_keyname = $keyname ? { '' => $title, default => $keyname } + $_home = $home ? { '' => "/home/${user}", default => $home } + $key_src_file = "${sshkeys::var::keymaster_storage}/${_keyname}/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": } + } +} diff --git a/external/sshkeys/manifests/setup_key_master.pp b/external/sshkeys/manifests/setup_key_master.pp new file mode 100644 index 00000000..d87e20cb --- /dev/null +++ b/external/sshkeys/manifests/setup_key_master.pp @@ -0,0 +1,87 @@ +# 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. sshkeys::create_key calls it to create virtual +# keys, which are realized in sshkeys::keymaster. +define sshkeys::setup_key_master ( + $ensure, + $force, + $keytype, + $length, + $maxdays, + $mindate +) { + include sshkeys::var + Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" } + File { + owner => puppet, + group => puppet, + mode => 600, + } + + $keydir = "${sshkeys::var::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"], + } + } +} diff --git a/external/sshkeys/manifests/var.pp b/external/sshkeys/manifests/var.pp new file mode 100644 index 00000000..16b1c03e --- /dev/null +++ b/external/sshkeys/manifests/var.pp @@ -0,0 +1,4 @@ +class sshkeys::var( + $keymaster_storage = "/var/lib/puppet-sshkeys" +) { +} |