class Hiera::Backend::Eyaml::Encryptors::Gpg

Constants

VERSION

Public Class Methods

create_keys() click to toggle source
# File lib/hiera/backend/eyaml/encryptors/gpg.rb, line 187
def self.create_keys
  STDERR.puts "The GPG encryptor does not support creation of keys, use the GPG command lines tools instead"
end
decrypt(ciphertext) click to toggle source
# File lib/hiera/backend/eyaml/encryptors/gpg.rb, line 148
def self.decrypt ciphertext
  gnupghome = self.option :gnupghome
  debug("GNUPGHOME is #{gnupghome}")

  unless defined?(GPGME)
    RubyGpg.config.homedir = gnupghome if gnupghome
    return RubyGpg.decrypt_string(ciphertext)
  end

  GPGME::Engine.home_dir = gnupghome

  ctx = if hiera?
    GPGME::Ctx.new
  else
    GPGME::Ctx.new(:passphrase_callback => method(:passfunc))
  end

  if !ctx.keys.empty?
    raw = GPGME::Data.new(ciphertext)
    txt = GPGME::Data.new

    begin
      txt = ctx.decrypt(raw)
    rescue GPGME::Error::DecryptFailed => e
      warn("Fatal: Failed to decrypt ciphertext (check settings and that you are a recipient)")
      raise e
    rescue Exception => e
      warn("Warning: General exception decrypting GPG file")
      raise e
    end

    txt.seek 0
    txt.read
  else
    warn("No usable keys found in #{gnupghome}. Check :gpg_gnupghome value in hiera.yaml is correct")
    raise ArgumentError, "No usable keys found in #{gnupghome}. Check :gpg_gnupghome value in hiera.yaml is correct"
  end
end
encrypt(plaintext) click to toggle source
# File lib/hiera/backend/eyaml/encryptors/gpg.rb, line 104
def self.encrypt plaintext
  unless defined?(GPGME)
    raise RecoverableError, "Encryption is only supported when using the 'gpgme' gem"
  end

  gnupghome = self.option :gnupghome
  GPGME::Engine.home_dir = gnupghome
  debug("GNUPGHOME is #{gnupghome}")

  ctx = GPGME::Ctx.new

  recipients = self.find_recipients
  debug("Recipents are #{recipients}")

  raise RecoverableError, 'No recipients provided, don\t know who to encrypt to' if recipients.empty?

  keys = recipients.map {|r| 
    key_to_use = ctx.keys(r).first 
    if key_to_use.nil? 
      raise RecoverableError, "No key found on keyring for #{r}"
    end
    key_to_use
  }
  debug("Keys: #{keys}")

  always_trust = self.option(:always_trust)
  unless always_trust
    # check validity of recipients (this is possibly naive, but better than the unhelpful
    # error that it would spit out otherwise)
    keys.each do |key|
      unless key.primary_uid.validity >= GPGME::VALIDITY_FULL
        raise RecoverableError, "Key #{key.sha} (#{key.email}) not trusted (if key trust is established by another means then specify always-trust)"
      end
    end
  end

  data = GPGME::Data.from_str(plaintext)
  crypto = GPGME::Crypto.new(:always_trust => always_trust)

  ciphertext = crypto.encrypt(data, :recipients => keys)
  ciphertext.seek 0
  ciphertext.read
end
find_recipients() click to toggle source
# File lib/hiera/backend/eyaml/encryptors/gpg.rb, line 60
def self.find_recipients
  recipient_option = self.option :recipients
  recipients = if !recipient_option.nil?
    debug("Using --recipients option")
    recipient_option.split(",")
  else
    recipient_file_option = self.option :recipients_file
    recipient_file = if !recipient_file_option.nil?
      debug("Using --recipients-file option")
      Pathname.new(recipient_file_option)
    else
      debug("Searching for any hiera-eyaml-gpg.recipients files in path")
      # if we are editing a file, look for a hiera-eyaml-gpg.recipients file
      filename = case Eyaml::Options[:source]
      when :file
        Eyaml::Options[:file]
      when :eyaml
        Eyaml::Options[:eyaml]
      else
        nil
      end

      if filename.nil?
        nil
      else
        path = Pathname.new(filename).realpath.dirname
        selected_file = nil
        path.descend{|path| path
          potential_file = path.join('hiera-eyaml-gpg.recipients')
          selected_file = potential_file if potential_file.exist? 
        }
        debug("Using file at #{selected_file}")
        selected_file
      end
    end

    unless recipient_file.nil?
      recipient_file.readlines.map{ |line| line.strip } 
    else
      []
    end
  end
end
passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd) click to toggle source
# File lib/hiera/backend/eyaml/encryptors/gpg.rb, line 41
def self.passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
  begin
      system('stty -echo')

      unless @@passphrase_cache.has_key?(uid_hint)
        @@passphrase_cache[uid_hint] = ask("Enter passphrase for #{uid_hint}: ") { |q| q.echo = '' }
        $stderr.puts
      end
      passphrase = @@passphrase_cache[uid_hint]

      io = IO.for_fd(fd, 'w')
      io.puts(passphrase)
      io.flush
    ensure
      (0 ... $_.length).each do |i| $_[i] = 0 end if $_
        system('stty echo')
    end
end