Using KMS in the shell
Purpose
Some notes on using AWS KMS from the shell
Create an AWS customer master key if you do not already have one
key_id=$(aws kms create-key | jq -r .KeyMetadata.KeyId)
aws kms create-alias --alias-name alias/my-test-key --target-key-id $key_id
Policy
- You should use policy to restrict access to the key
- In this sample I presume you have access to the key
Script with encrypt\decrypt and some test functions
#!/bin/bash
# This assumes you have configured the AWS region and credentials, if not it will fail
# We do not set errexit or pipefail as the environment sourcing this should configure this
# Can use set -o to check
kms-decrypt()
{
context=$1
cipher=$2
region=${3:-$AWS_REGION}
aws kms decrypt --ciphertext-blob fileb://<(echo $cipher | base64 --decode) --region $region --output text --query Plaintext | base64 --decode
}
kms-encrypt()
{
key=$1
context=$2
plain=$3
region=${4:-$AWS_REGION}
aws kms encrypt --key-id alias/${key} --plaintext "$plain" --region $region --output text --query CiphertextBlob
}
# Tests
assert()
{
# If you have set errexit this will fail and exit immediately, should test with set +o errexit
eval "$1"
[[ $? -eq 0 ]] && echo -e "\e[32m${FUNCNAME[1]}: ${1} passed\e[0m" || echo -e "\e[31m ${FUNCNAME[1]}: ${1} failed\e[0m"
}
test-kms-roundtrip-with-no-context()
{
key=my-test-key
context=
original_data='eykjsgh$^%46546112--dff09865-END'
cipher=$(kms-encrypt $key "$context" "$original_data")
plain=$(kms-decrypt "$context" "$cipher")
assert "[ '$original_data' == '$plain' ]"
}
test-kms-roundtrip-with-context()
{
key=my-test-key
context='k1=v1,k2=v2'
original_data='eykjsgh$^%46546112--dff09865-OTHER-END.'
cipher=$(kms-encrypt $key "$context" "$original_data")
plain=$(kms-decrypt "$context" "$cipher")
assert "[ '$original_data' == '$plain' ]"
}