Report abuse

require 'net/http'

# Query db to fetch latest ssh known hosts, and store locally for 24 hours.
module Puppet::Parser::Functions
 newfunction(:sshkeyfromdb, :type => :rvalue) do |args|
   #local cache file on each puppetmaster
  ssh_keys_file = "/tmp/sshkeys"
  #URL to query
  host = "puppet"
  url = "/setting/ssh_keys"
  #Time to keep cache - e.g. 24 hours.
  ttl = (60 * 60 * 24)

  # create a cache file
  if not File.exist?(ssh_keys_file) or File.mtime(ssh_keys_file) < (Time.now - ttl) # file is older than 24hours.
    keys = Net::HTTP.get host,url
    File.new(ssh_keys_file,"w", 0600).write(keys)
    # convert Marshal to hash
    keys = Marshal.load keys
  else
    keys = Marshal.load File.open(ssh_keys_file).read
  end
  case args[0].downcase
    when nil
      warn "Must supply key type - RSA or DSA"
      exit 1 
    when "hosts" # return an array of all hosts has a ssh public key
      hosts = Array.new
      keys.each_key do |fqdn| # return an array of all hosts
        ipaddress = keys[fqdn]["ipaddress"]  
        hosts << [fqdn, ipaddress, 'ssh-rsa', keys[fqdn]["rsa"]] if keys[fqdn].has_key?('rsa') 
        hosts << [fqdn, ipaddress, 'ssh-dss', keys[fqdn]["dsa"]] if keys[fqdn].has_key?('dsa') 
      end
      return hosts
    end
  end
 end





USAGE:

class ssh::knownhosts {
  $ssh_hosts = sshkeyfromdb(hosts)

  # Generate known_hosts out of a template
  file{"/etc/ssh/ssh_known_hosts":
    owner   => root, 
    group   => root, 
    mode    => 644, 
    content => template("ssh/known_hosts.erb"), 
    schedule => "maint",
    require  => Schedule["maint"]
  }
}

template:
<%# generate ssh keys from sshkeyfromdb function, not using native sshkey type do to performance difference %>
<% ssh_hosts.each do |host| 
  fqdn, ipaddress, key_type, key = host[0], host[1], host[2], host[3] 
  hostname = fqdn.split('.')[0] -%>
<%="#{hostname},#{fqdn},#{ipaddress} #{key_type} #{key}"%>
<%end -%>