0

I am writing a puppet Ceph deployment module and need to generate keys on an admin node and distribute them to the monitor nodes. I have written server-side functions to retrieve the keys once they are generated, but would like to only distribute those keys once they exist.

  • The manifest for the admin node generates the cluster keys
  • Manifests for the monitor and management nodes need to include those keys as file resources
  • The manifests should not fail to compile (or generate undue log volume) if they keys have not yet been generated
  • The file resources need to be named as they are per-requisites for other resources

n.b. The examples are from Puppet3 so no Ruby dispatch :(

What is the philosophically pure approach to gather and distribute keys?

Sample code: manifests/admin_node.pp:

exec { "make_${cluster[name]}_${name}_keyring":
    command     => "/usr/bin/ceph-authtool --create-keyring ${ring[file]} --gen-key -n ${ring[name]} ${ring[auth]}",
    require     => [ File[$confdir, $bootdir], Package['ceph-common'], ],
    creates     => $ring[file],
}

lib/puppet/parser/functions/get_remote_file.rb:

module Puppet::Parser::Functions
    newfunction(:get_remote_file, :type => :rvalue) do |args|
        return "Error 3: " + args.length.to_s + " arguments were provided to get_remote_file.rb.  Required is 3 to 5." if args.length < 3 or args.length > 5
        remote_host = args[0]
        remote_path = args[1]
        local_path  = args[2]
        local_user  = (args.length > 3) ? 'runuser -l ' + args[3] + ' ' : ''
        remote_user = (args.length > 4) ? args[4] + '@' : ''

        # Is the file already down?
        return 0 if File.exist?(local_path)

        `"#{local_user}bash -c 'scp #{remote_user}#{remote_host}:#{remote_path} #{local_path} 2> /dev/null'"`
        return $?.exitstatus
    end
end

manifests/monitor_node.pp:

unless file_exists($master_key) {
    get_remote_file($adm_node, $monitor_keyring, $master_key)
}
exec { "check_${cluster[name]}.mon.keyring":
    command => '/bin/yes',
    onlyif  => "/usr/bin/test -e $master_key",
}
file { "$libdir/${cluster[name]}.mon.keyring":
    ensure  => $f_action,
    source  => "puppet:///modules/ceph$libdir/${cluster[name]}.mon.keyring",
    require => Exec["check_${cluster[name]}.mon.keyring"],
}

Thanks for any ideas on how to tackle this. I understand that this is... dis-incentivized in Puppet. What is a good approach?

littlelion
  • 31
  • 5
  • It sounds like a job for exported resources. For that purpose, do the wanted files have distinct names for each node? – John Bollinger Nov 17 '18 at 12:43
  • Would heavily recommend using a native API and not a raw shell command for `scp` in that function if you want to go that route. – Matthew Schuchard Nov 17 '18 at 13:59
  • Thanks John, yes, the files are unique across the namespace. I have installed puppetDB and am looking to use Exported Resources, but it seems a pretty heavy lift to transfer a key file. I'll comment back here once I get things running. – littlelion Nov 18 '18 at 02:24
  • I agree Matt, that was a quick hack to see if I could get something working. Turned out to be a dead end which is why I posted here to see if there was a better approach someone could recommend. – littlelion Nov 18 '18 at 02:25

0 Answers0