Move bacula::bacula_ssl_{server,client}_{cert,key} to hiera
[mirror/dsa-puppet.git] / modules / ssh / manifests / authorized_key_add.pp
index 3e700cc..aae3ed9 100644 (file)
@@ -1,24 +1,68 @@
-# store ssh authorized_keys snippets that roles on different hosts can then
-# collect using ssh::authorized_key_collect
-
+# export sshd's authorized_keys fragments
+#
+# This creates exported sshd `authorized_keys` snippets that different
+# hosts can then collect using `ssh::authorized_key_collect`.
+#
+# This is a replacement for the builtin ssh_authorized_keys, although
+# it requires exported resources to work.
+#
+# The builtin type had too many problems to overcome to be useful in
+# our environment. A short overview of known issues, some of which are
+# security-sensitive:
+#
+# * MODULES-7595: ssh_authorized_key should be able to take a ready-made OpenSSH public key
+# * MODULES-7596: puppet ssh_authorized_key not purged as expected
+# * MODULES-9726: allow read-only authorized_keys
+# * MODULES-7610: sshkey uses name instead of title for duplication check
+#
+# There are many more issues on the sshkeys module, which doesn't seem
+# to be very well maintained anyways:
+#
+# https://tickets.puppetlabs.com/browse/MODULES-9726?jql=project%20%3D%20MODULES%20AND%20component%20%3D%20sshkeys_core
+#
+# @param target_user the filename to save the key under
+#
+# @param collect_tag which tag to export this resource as
+#
+# @param options a list of options, defaults to ["restrict"]
+#
+# @param command the command to enforce for this keyfile
+#
+# @param from a list of IPv4 or IPv6 address to pass to the
+#                   key's `from=` parameter.
+#
+# @param key the actual public key, including ssh-*, the public key
+#            material and the comment
 define ssh::authorized_key_add(
   String $target_user,
-  String $command,
-  String $key,
   Variant[Array[String], String] $collect_tag,
-  String $restrict = 'restrict',
-  Array[Stdlib::IP::Address] $from_hosts = $base::public_addresses,
+  Array[String] $options = ['restrict'],
+  Optional[String] $command = '',
+  Optional[Array[Stdlib::IP::Address]] $from = $base::public_addresses,
+  Optional[String] $key = undef,
 ) {
-  $from = $from_hosts.join(',')
+  $ssh_from_string = $from.join(',')
+  if $command {
+    $options_command = ["command=\"${command}\""]
+  } else {
+    $options_command = []
+  }
+  if $ssh_from_string {
+    $options_from = ["from=\"${ssh_from_string}\""]
+  } else {
+    $options_from = []
+  }
+  $real_options = $options_command + $options_from + $options
+  $options_string = $real_options.join(',')
 
-  if (size(split($key, "\n")) > 1) {
+  if ($key and size(split($key, "\n")) > 1) {
     fail('More than one line in key for ssh::authorized_key')
   }
   if (size(split($command, '"')) > 1) {
     fail('command must not contain double quotes')
   }
-  if (size(split($from, '"')) > 1) {
-    fail('from_hosts must not contain double quotes')
+  if (size(split($ssh_from_string, '"')) > 1) {
+    fail('from must not contain double quotes')
   }
 
   if $collect_tag =~ String {
@@ -29,27 +73,28 @@ define ssh::authorized_key_add(
   $ssh_tags = $raw_tags.map |$t| { "ssh::authorized_key::fragment::${t}::${target_user}" }
   $ferm_tags = $raw_tags.map |$t| { "ssh::authorized_key::ferm::${t}::${target_user}" }
 
-  $from_space = $from_hosts.join(' ')
+  $ferm_from_string = $from.join(' ')
 
   if $key {
     @@concat::fragment { "ssh::authorized_key::${name} ${target_user} from ${::hostname}":
       tag     => $ssh_tags,
-      target  => "/etc/ssh/userkeys/${target_user}",
-      order   => '200',
+      target  => "/etc/ssh/puppetkeys/${target_user}",
       content => @("EOF"),
                  # from ${::fqdn}
-                 command="${command}",from="${from}",${restrict} ${key}
+                 ${options_string} ${key}
                  | EOF
     }
   } else {
-    notify{ "Warning, ssh key for ${name}, ${target_user} not defined (yet?).": }
+    notify { "Warning, ssh key for ${name}, ${target_user} not defined (yet?).":
+      loglevel => warning,
+    }
   }
 
   @@ferm::rule { "ssh-${raw_tags[0]}_${target_user}-${name}_from_${::hostname}":
-    tag         => $ssh_tags,
+    tag         => $ferm_tags,
     description => "allow ssh for ssh to ${target_user}",
     domain      => '(ip ip6)',
     chain       => 'ssh',
-    rule        => "saddr (${from_space}) ACCEPT",
+    rule        => "saddr (${ferm_from_string}) ACCEPT",
   }
 }