Created
March 29, 2016 00:45
-
-
Save bmhatfield/53b863dd17df844a11de to your computer and use it in GitHub Desktop.
Encrypt, Edit and key-rotate databags.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'chef/knife' | |
module LocalDatabags | |
class Encrypt < Chef::Knife | |
deps do | |
require 'chef/encrypted_data_bag_item' | |
end | |
banner "knife encrypt BAGNAME ITEM KEYFILE" | |
def validate! | |
unless name_args.length == 3 | |
ui.fatal "Missing Arguments" | |
show_usage | |
exit 1 | |
end | |
@bagname = name_args[0] | |
@itemname = name_args[1] | |
@keyfile = name_args[2] | |
@databag_file = "data_bags/#{@bagname}/#{@itemname}.json" | |
unless Dir.exists? 'data_bags' | |
ui.fatal "Could not find 'data_bags' directory" | |
exit 1 | |
end | |
begin | |
unless File.exists? @keyfile | |
raise | |
end | |
@secret = Chef::EncryptedDataBagItem.load_secret(@keyfile) | |
rescue | |
ui.fatal "Unable to load key '#{@keyfile}'" | |
exit 1 | |
end | |
end | |
def run | |
validate! | |
# Force config to chef-solo for our current purposes, which allows | |
# loading of databags from the :data_bag_path, allowing us to edit | |
# existing databags. | |
Chef::Config[:solo] = true | |
Chef::Config[:data_bag_path] = 'data_bags' | |
if File.exists? @databag_file | |
data = Chef::EncryptedDataBagItem.load(@bagname, @itemname, @secret).to_hash | |
else | |
data = {"id" => @itemname} | |
end | |
edited = ui.edit_data(data, parse_output=true) | |
if edited != data | |
ui.msg "Saving updated databag..." | |
encrypted_data = Chef::EncryptedDataBagItem.encrypt_data_bag_item(edited, @secret) | |
FileUtils.mkpath("data_bags/#{@bagname}") | |
File.open(@databag_file, 'w') do |f| | |
f.print encrypted_data.to_json | |
end | |
end | |
end | |
end | |
class EncryptRotate < Chef::Knife | |
deps do | |
require 'chef/encrypted_data_bag_item' | |
end | |
banner "knife encrypt rotate KEYFILE_OLD KEYFILE_NEW" | |
def validate! | |
unless name_args.length == 2 | |
ui.fatal "Missing Arguments" | |
show_usage | |
exit 1 | |
end | |
@old_key_path = name_args[0] | |
@new_key_path = name_args[1] | |
unless Dir.exists? 'data_bags' | |
ui.fatal "Could not find 'data_bags' directory" | |
exit 1 | |
end | |
begin | |
unless File.exists? @old_key_path | |
raise | |
end | |
@old_secret = Chef::EncryptedDataBagItem.load_secret(@old_key_path) | |
rescue | |
ui.fatal "Unable to load key '#{old_key_path}'" | |
exit 1 | |
end | |
begin | |
unless File.exists? @new_key_path | |
raise | |
end | |
@new_secret = Chef::EncryptedDataBagItem.load_secret(@new_key_path) | |
rescue | |
ui.fatal "Unable to load key '#{@new_key_path}'" | |
exit 1 | |
end | |
end | |
def rotate(directory) | |
bags = Dir.entries(directory) | |
bags.each do |bag| | |
if ['README.md', '.', '..'].include?(bag) | |
next | |
end | |
if File.directory?("data_bags/#{bag}") | |
items = Dir.entries("data_bags/#{bag}") | |
items.each do |item_file_name| | |
if ['README.md', '.', '..'].include?(item_file_name) | |
next | |
end | |
item_name = item_file_name[0..item_file_name.rindex('.')-1] | |
begin | |
data = Chef::EncryptedDataBagItem.load(bag, item_name, @old_secret).to_hash | |
encrypted_data = Chef::EncryptedDataBagItem.encrypt_data_bag_item(data, @new_secret) | |
ui.msg "Writing data_bags/#{bag}/#{item_file_name}" | |
File.open("data_bags/#{bag}/#{item_file_name}", 'w') do |f| | |
f.print encrypted_data.to_json | |
end | |
rescue | |
ui.msg "Skipping #{bag} #{item_name} - not encrypted?" | |
end | |
end | |
end | |
end | |
end | |
def run | |
validate! | |
# Force config to chef-solo for our current purposes, which allows | |
# loading of databags from the :data_bag_path, allowing us to edit | |
# existing databags. | |
Chef::Config[:solo] = true | |
Chef::Config[:data_bag_path] = 'data_bags' | |
rotate('data_bags') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment