Search code examples
rubyencryptionchef-infraknifedatabags

Encrypt data bag from inside of ruby without relying on knife


At the moment to encrypt a data bag, I have to do : system "knife data bag from file TemporaryEncrypting \"#{enc_file_path}\" --secret-file #{Secret_Key_Path}"

and that doesn't work because knife can't find a config file and I can't seem to get it read the one in C:\chef.

How do I do this from within ruby?


Solution

  • I worked out how to encrypt inside of ruby, just use this code:

    require 'chef/knife'
    #require 'chef/encrypted_data_bag_item' #you need to do this in chef version 12, they've moved it out of knife and into it's own section
    require 'json'
    
    secret = Chef::EncryptedDataBagItem.load_secret Secret_Key_Path
    
    to_encrypt = JSON.parse(json_to_encrypt)
    
    encrypted_data = Chef::EncryptedDataBagItem.encrypt_data_bag_item to_encrypt, secret
    

    Answer achieved with information from this answer, here is the code in question:

    namespace 'databag' do
      desc 'Edit encrypted databag item.'
      task :edit, [:databag, :item, :secret_file] do |t, args|
        args.with_defaults :secret_file => "#{ENV['HOME']}/.chef/encrypted_data_bag_secret"
        secret = Chef::EncryptedDataBagItem.load_secret args.secret_file
        item_file = "data_bags/#{args.databag}/#{args.item}.json"
        tmp_item_file = "/tmp/#{args.databag}_#{args.item}.json"
        begin
          #decrypt data bag into tmp file
          raw_hash = Chef::JSONCompat.from_json IO.read item_file
          databag_item = Chef::EncryptedDataBagItem.new raw_hash, secret
          IO.write tmp_item_file, Chef::JSONCompat.to_json_pretty( databag_item.to_hash )
          #edit tmp file
          sh "#{ENV['EDITOR']} #{tmp_item_file}"
          #encrypt tmp file data bag into original file
          raw_hash = Chef::JSONCompat.from_json IO.read tmp_item_file
          databag_item = Chef::EncryptedDataBagItem.encrypt_data_bag_item raw_hash, secret
          IO.write item_file, Chef::JSONCompat.to_json_pretty( databag_item )
        ensure
          ::File.delete tmp_item_file #ensure tmp file deleted.
        end
      end
    end