Skip to content

Instantly share code, notes, and snippets.

@mtahle
Last active July 12, 2024 21:27
Show Gist options
  • Save mtahle/3548069e126e08567bb8f5c29fdb76a0 to your computer and use it in GitHub Desktop.
Save mtahle/3548069e126e08567bb8f5c29fdb76a0 to your computer and use it in GitHub Desktop.
encrypt and decrypt a backup file using AWS Key Management Service (KMS) and AWS S3.
#!/bin/sh
# This script provides functionality to encrypt and decrypt a backup file using AWS Key Management Service (KMS) and AWS S3.
# It takes two main commands: 'encrypt' and 'decrypt'.
# The 'encrypt' command encrypts the backup file using a data encryption key (DEK) generated by AWS KMS.
# The encrypted backup file and the encrypted DEK are then uploaded to an S3 bucket.
# The 'decrypt' command downloads the encrypted backup file and the encrypted DEK from the S3 bucket.
# It then decrypts the backup file using the DEK and saves it to a local directory.
#Author:
# Mujahed Al-Tahleh,DevOps Consultant, AWS Professional Services, GitHub: @mtahle
set -e
# Set locale to handle byte sequences correctly
export LC_ALL=C
# Function to encrypt the file
encrypt() {
# Check if required environment variables are set
: "${KMS_KEY_ID?Need to set KMS_KEY_ID}"
: "${S3_BUCKET_NAME?Need to set S3_BUCKET_NAME}"
# Generate a data encryption key (DEK) and capture both plaintext and ciphertext
DEK_OUTPUT=$(aws kms generate-data-key --key-id $KMS_KEY_ID --key-spec AES_256 --output json)
# Extract the plaintext DEK and the ciphertext blob from the output
DEK_PLAINTEXT=$(echo $DEK_OUTPUT | jq -r '.Plaintext' | base64 --decode | tr -d '\n\r ')
DEK_CIPHERTEXT=$(echo $DEK_OUTPUT | jq -r '.CiphertextBlob')
# Encrypt the file using the plaintext DEK
openssl enc -aes-256-cbc -salt -in /shared/file.txt -out /shared/file.txt.enc -pass pass:$DEK_PLAINTEXT
echo $DEK_CIPHERTEXT > /tmp/dek_ciphertext
# Organize S3 by date
DATE=$(date +%Y-%m-%d)
# Upload the encrypted file and encrypted DEK to S3
aws s3 cp /shared/file.txt.enc s3://$S3_BUCKET_NAME/backups/$DATE/file.txt.enc
aws s3 cp /tmp/dek_ciphertext s3://$S3_BUCKET_NAME/backups/$DATE/dek_ciphertext
shred -u /shared/*
shred -u /tmp/dek_ciphertext
echo "File encryption and upload successful."
}
# Function to decrypt the file
decrypt() {
# Check if required environment variables are set
: "${KMS_KEY_ID?Need to set KMS_KEY_ID}"
: "${S3_BUCKET_NAME?Need to set S3_BUCKET_NAME}"
: "${DATE?Need to set DATE}" # The date folder where the file and DEK are stored
echo "Downloading encrypted DEK and file from S3..."
aws s3 cp s3://$S3_BUCKET_NAME/backups/$DATE/dek_ciphertext /tmp/dek_ciphertext
aws s3 cp s3://$S3_BUCKET_NAME/backups/$DATE/file.txt.enc /tmp/file.txt.enc
# Verify the files are downloaded successfully
if [ ! -f /tmp/dek_ciphertext ]; then
echo "Error: Failed to download /tmp/dek_ciphertext"
exit 1
fi
if [ ! -f /tmp/file.txt.enc ]; then
echo "Error: Failed to download /tmp/file.txt.enc"
exit 1
fi
cat /tmp/dek_ciphertext | base64 --decode > /tmp/decoded_dek_ciphertext
# Decrypt the DEK using AWS KMS
DEK_PLAINTEXT=$(aws kms decrypt --ciphertext-blob fileb:///tmp/decoded_dek_ciphertext --output text --query Plaintext | base64 --decode )
if [ -z "$DEK_PLAINTEXT" ]; then
echo "Error: Failed to decrypt DEK"
exit 1
fi
# Decrypt the file using the plaintext DEK
openssl enc -d -aes-256-cbc -in /tmp/file.txt.enc -out /tmp/file.txt -pass pass:$DEK_PLAINTEXT
# Verify the decryption was successful
if [ ! -f /tmp/file.txt ]; then
echo "Error: Decryption failed"
exit 1
fi
# Clean up
unset DEK_PLAINTEXT
rm /tmp/dek_ciphertext
echo "Decryption successful. Decrypted file is at /tmp/file.txt"
}
# Main script logic
case "$1" in
encrypt|e)
encrypt
;;
decrypt|d)
decrypt
;;
*)
echo "Usage: $0 {encrypt|decrypt}"
echo " encrypt: Encrypt the file"
echo " decrypt: Decrypt the file"
echo " Note: When using 'decrypt', ensure to set the DATE environment variable in the format YYYY-MM-DD"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment