Skip to content

Instantly share code, notes, and snippets.

@asdqwex
Created July 15, 2015 20:48
Show Gist options
  • Save asdqwex/78d60af9e34a888c0918 to your computer and use it in GitHub Desktop.
Save asdqwex/78d60af9e34a888c0918 to your computer and use it in GitHub Desktop.
4jim
#!/bin/bash
# Author: Jim Rosser
# Email: jarosser06@gmail.com
#
# Cloning a data bag:
# This will create a new data bag with the same items as the existing
# data bag. If -n is not set it will create a new key and encrypt the
# new data bag with that.
#
# Create data bag new_data_bag that has been encrypted with a new key:
# data-bag-secrets -e my_secret_file clone existing_data_bag new_data_bag
#
# Clone existin_data_bag to new_data_bag encrypted with the same key:
# data-bag-secrets -e my_secret_file -n my_secret_file clone existing_data_bag new_data_bag
#
# Rotating a data bag:
# This will rotate one or more encrypted data bags with a new key.
#
# Rotate bag1, bag2, and bag3 with a pre-created secret file:
# data-bag-secrets -e old_secret_file -n new_secret_file rotate bag1,bag2,bag3
#
# Rotate bag1 with a key generated by this command, the key used will be
# named secret.pem and located in the current working directory:
# data-bag-secrets -e old_secret_file rotate bag1
#
existing_key=""
new_key=""
random_str=$(cat /dev/urandom | LC_CTYPE=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
tmp_dir="/tmp/${random_str}"
COMMAND_NAME="data-bag-secrets"
function usage {
cat <<EOF
Some helpful commands to manipulate secret data bags.
Usage:
${COMMAND_NAME} [opts] command [command args]
Options:
-h - show this usage
-e - existing data bag secret file
-n - new secret file
Commands:
rotate - rotates a data bag with a new secret file
clone - clones a data bag to a new name
kitchen - clones a data bag or all data bags to local secrets
EOF
}
function cleanup {
rm -rf $tmp_dir
}
function key_gen {
openssl rand -base64 512 | LC_CTYPE=C tr -d '\r\n' > secret.pem
}
function new_key_warn {
if [ -z $new_key ]; then
echo "Warning: you did not pass a new key so one will be gereated for you!"
fi
}
function fail() {
message=$1
echo "Error: ${message}"
exit 1
}
function fail_with_usage() {
message=$1
echo -e "\nError: ${message}\n"
usage
exit 1
}
function download_data_bag() {
existing_data_bag=$1
if [ -z $existing_data_bag ]; then
fail "download_data_bag() missing argument existing_data_bag"
fi
data_bag_items=$(knife data bag show ${existing_data_bag})
if ! [ $? -eq 0 ]; then
fail "knife data bag show ${existing_data_bag} returned non zero value"
fi
dir=${tmp_dir}/${existing_data_bag}
mkdir -p $dir
for item in $data_bag_items
do
knife data bag show $existing_data_bag $item -F json --secret-file $existing_key > ${dir}/${item}.json
## Fail out if knife returns something other than 0
if ! [ $? -eq 0 ]; then
fail "something went wrong with 'knife data bag show ${existing_data_bag} ${item} -F json --secret-file ${existing_key} > ${dir}/${item}.json'"
fi
done
}
function clone_data_bag() {
existing_data_bag=$1
new_data_bag=$2
if [ -z $existing_data_bag ]; then
fail "download_data_bag() missing argument existing_data_bag"
fi
if [ -z $new_data_bag ]; then
fail "clone_data_bag() missing argument new_data_bag"
fi
if [ -z $existing_key ]; then
fail "missing existing secret key"
fi
mkdir $tmp_dir
download_data_bag $1
## Assume we are rotating the same data bag if both are the same
if ! [ $existing_data_bag == $new_data_bag ]; then
mv ${tmp_dir}/${existing_data_bag} ${tmp_dir}/${new_data_bag}
fi
key=$new_key
if [ -z $key ]; then
new_key_warn
key_gen
key=$(pwd)/secret.pem
fi
knife data bag create $new_data_bag
knife data bag from file $new_data_bag ${tmp_dir}/${new_data_bag} --secret-file $key
## Call cleanup function to make sure the secrets are cleaned up
## only if nothing went wrong
if [ $? -eq 0 ]; then
cleanup
else
fail "something went wrong with the upload, downloaded data is located in ${tmp_dir}"
fi
}
while getopts ":e:n:h" flag
do
case $flag in
h)
usage
exit 1
;;
e)
existing_key=$OPTARG
;;
n)
new_key=$OPTARG
;;
esac
done
shift $((OPTIND-1))
case $1 in
rotate)
if [ "$2" == "-h" ]; then
echo "${COMMAND_NAME} -e <existing-key> [-n <new-key>] rotate <comma delimited data-bags>"
exit 1
fi
## Fail out if no data bag is passed
if [ -z $2 ]; then
fail "must pass at least one data bag to rotate"
fi
for bag in $(echo ${2} | LC_CTYPE=C tr ',' ' ')
do
clone_data_bag $bag $bag
done
;;
clone)
if [ "$2" == "-h" ]; then
echo "${COMMAND_NAME} -e <existing-key> -n <new-key> clone <existing-data-bag-name> <new-data-bag-name>"
exit 1
fi
knife data bag show $new_data_bag &> /dev/null
if [ $? -eq 0 ]; then
fail "data bag ${new_data_bag} already exists"
fi
clone_data_bag $2 $3
;;
kitchen)
if [ "$2" == "-h" ]; then
echo "${COMMAND_NAME} -e <existing-key> kitchen"
exit 1
fi
echo "Not yet implemented... Jim is lazy"
;;
*)
fail "unknown commmand ${1}"
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment