require 'fileutils' module Ironfan # # A private key -- chef client key, ssh key, etc. # # The key is a pro class PrivateKey < Ironfan::DslObject attr_reader :name attr_reader :proxy attr_reader :on_update # # PrivateKey.new('bob') # # @yield a block, executed in caller's context, when the body is updated # @yieldparam the updated body def initialize(name, proxy=nil, &on_update) @name = name @proxy = proxy @on_update = on_update end def filename File.join(key_dir, "#{name}.pem") end def save return unless @body if Ironfan.chef_config[:dry_run] Chef::Log.debug(" key #{name} - dry run, not writing out key") return end ui.info( " key #{name} - writing to #{filename}" ) FileUtils.mkdir_p(File.dirname(filename)) File.open(filename, "w", 0600){|f| f.print( @body ) } end def load return unless File.exists?(filename) self.body = File.read(filename).chomp end def body=(content) @body = content on_update.call(content) if on_update content end def self.create!(name, *args, &block) obj = self.new(name, *args, &block) obj.create_proxy! obj end def to_s [super[0..-2], @name, @proxy, @body.to_s[32..64], '...', @body.to_s[-60..-30]].join(" ").gsub(/[\r\n\t]+/,'') + '>' end end class ChefClientKey < PrivateKey def body return @body if @body if proxy && proxy.private_key && (not proxy.private_key.empty?) @body = proxy.private_key else load end @body end def key_dir Chef::Config.client_key_dir || "/tmp/#{ENV['USER']}-client_keys" end end class DataBagKey < PrivateKey def body return @body if @body @body end def random_token require "digest/sha2" digest = Digest::SHA512.hexdigest( Time.now.to_s + (1..10).collect{ rand.to_s }.join ) 5.times{ digest = Digest::SHA512.hexdigest(digest) } digest end def key_dir return Chef::Config.data_bag_key_dir if Chef::Config.data_bag_key_dir dir = "#{ENV['HOME']}/.chef/credentials/data_bag_keys" warn "Please set 'data_bag_key_dir' in your knife.rb. Will use #{dir} as a default" dir end end class Ec2Keypair < PrivateKey def body return @body if @body if proxy && proxy.private_key && (not proxy.private_key.empty?) @body = proxy.private_key else load end @body end def create_proxy! safely do step(" key #{name} - creating", :green) @proxy = Ironfan.fog_connection.key_pairs.create(:name => name.to_s) end Ironfan.fog_keypairs[name] = proxy self.body = proxy.private_key save end def key_dir if Chef::Config.ec2_key_dir return Chef::Config.ec2_key_dir else dir = "#{ENV['HOME']}/.chef/credentials/ec2_keys" warn "Please set 'ec2_key_dir' in your knife.rb. Will use #{dir} as a default" dir end end end end