Skip to content

Instantly share code, notes, and snippets.

@aaronjensen
Created November 21, 2012 04:39
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save aaronjensen/4123044 to your computer and use it in GitHub Desktop.
Save aaronjensen/4123044 to your computer and use it in GitHub Desktop.
Edit encrypted data bags for use with chef-solo and knife-solo
#!/usr/bin/env ruby
Dir.chdir File.join(__FILE__, "../..")
unless ENV['EDITOR']
puts "No EDITOR found. Try:"
puts "export EDITOR=vim"
exit 1
end
unless ARGV.count == 2
puts "usage: #{$0} <data bag> <item name>"
exit 1
end
require 'chef/encrypted_data_bag_item'
require 'json'
require 'tempfile'
data_bag = ARGV[0]
item_name = ARGV[1]
encrypted_path = "data_bags/#{data_bag}/#{item_name}.json"
unless File.exists? encrypted_path
puts "Cannot find #{File.join(Dir.pwd, encrypted_path)}"
exit 1
end
data_bag_key_path = File.join(Dir.pwd, "data_bag_key")
unless File.exists? data_bag_key_path
puts "Get the data_bag_key and put it in #{data_bag_key_path}."
exit 1
end
secret = Chef::EncryptedDataBagItem.load_secret('data_bag_key')
decrypted_file = Tempfile.new ["#{data_bag}_#{item_name}",".json"]
at_exit { decrypted_file.delete }
encrypted_data = JSON.parse(File.read(encrypted_path))
plain_data = Chef::EncryptedDataBagItem.new(encrypted_data, secret).to_hash
decrypted_file.puts JSON.pretty_generate(plain_data)
decrypted_file.close
system "#{ENV['EDITOR']} #{decrypted_file.path}"
plain_data = JSON.parse(File.read(decrypted_file.path))
encrypted_data = Chef::EncryptedDataBagItem.encrypt_data_bag_item(plain_data, secret)
File.write encrypted_path, JSON.pretty_generate(encrypted_data)
@srigi
Copy link

srigi commented Jan 5, 2013

Thats awesome! Works like a charm. THX.

@gansbrest
Copy link

Yep, great script - thanks

@SFEley
Copy link

SFEley commented Apr 22, 2013

Indeed, most handy. I've adapted the core of this into a Rake task for my company's ops project. Thank you!

@subdigital
Copy link

+1 - simple solution, thanks :)

@jdeebee
Copy link

jdeebee commented Jun 14, 2015

Thank you man, really appreciate it. As you know Chef doesn't provide a method to iterate over data bag items' attributes. Running something like this was the only way to save a data bag item to a (temporary) json file. As a reference for those non-ruby guys who want to use this in a Chef recipe:

# load my secret key from a path specified in a Chef attribute
secret_key = Chef::EncryptedDataBagItem.load_secret("#{node[:my_repo_name][:secret_key_file_path]}")

# use the ruby_block statement to run arbitrary Ruby code in the Chef DSL
ruby_block "decrypt passwords" do
  block do
    encrypted_path = "/home/me/data_bags/secrets/passwords.json"
    encrypted_data = JSON.parse(File.read(encrypted_path))
    plain_data = Chef::EncryptedDataBagItem.new(encrypted_data, secret_key).to_hash
    File.open('/opt/me/passwords.json', 'w') { |f|
      f.write(JSON.pretty_generate(plain_data))
    }
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment