Skip to content

Instantly share code, notes, and snippets.

@pirate
Last active January 30, 2021 01:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pirate/0e6d6a23bf5df01b4c6a8451414ade4a to your computer and use it in GitHub Desktop.
Save pirate/0e6d6a23bf5df01b4c6a8451414ade4a to your computer and use it in GitHub Desktop.
Get and set config & secret values in DNS TXT records (via CloudFlare API)
#!/usr/bin/env fish
# Script to store and retrieve config/secret key=value pairs in Cloudflare DNS records
# Encrypts secrets with a specified passphrase + salt using AES-256-CBC
#
# Usage:
#
# $ set_config some_config_key "example config value abc"
# $ get_config some_config_key
# example config value abc
#
# $ set_secret some_secret_key "example secret value xyz" "somelongrandompassphrase123"
# $ get_secret some_secret_key "somelongrandompassphrase123"
# example secret value xyz
# https://dash.cloudflare.com/profile/api-tokens
set CF_API_KEY "YOUR_CLOUDFLARE_API_BEARER_TOKEN_HERE"
set CF_API_ZONE "YOUR_CLOUDFLARE_DNS_ZONE_HERE_abc1234"
set CONFIG_DNS_DOMAIN "example.com"
set CONFIG_DNS_TTL 120
function aes_encrypt --argument-names=passphrase --description "echo 'plaintext' | aes_encrypt 'passphrase' > cyphertext.txt"
openssl enc -aes-256-cbc -md sha512 -base64 -A -pbkdf2 --iter 10000 -pass "pass:$passphrase" -e -in /dev/stdin -out /dev/stdout 2>/dev/null
end
function aes_decrypt --argument-names=passphrase --description "echo 'cyphertext' | aes_decrypt 'passphrase' > plaintext.txt"
openssl enc -aes-256-cbc -md sha512 -base64 -A -pbkdf2 --iter 10000 -pass "pass:$passphrase" -d -in /dev/stdin -out /dev/stdout 2>/dev/null
end
# Quick check to make sure aes_encrypt, aes_decrypt are working in isolation:
# set initial "mary had a little lamb"
# echo 'initial:' "$initial"
# set cyphertext (echo "$initial" | aes_encrypt "somelongrandompasswordhere")
# echo 'cypertext:' "$cyphertext"
# set plaintext (echo "$cyphertext" | aes_decrypt "somelongrandompasswordhere")
# echo 'plaintext:' "$plaintext"
function get_config --argument-names=key --description "lookup the value of a given config [key]"
set config_key "$key.$CONFIG_DNS_DOMAIN"
# we can get the values via DNS, but it lags, so get it from cloudflare's API for faster results
# set config_value (dig +short @1.1.1.1 "$config_key" TXT | xargs | perl -pe 's/ //gm') # too slow
curl -X GET -s "https://api.cloudflare.com/client/v4/zones/$CF_API_ZONE/dns_records?name=contains:$config_key&type=TXT" \
-H "Authorization: Bearer $CF_API_KEY" \
-H "Content-Type: application/json" \
| jq -e -r '.result[0] | .content // ""' | grep --color=never .
end
function set_config --argument-names=key,value --description "set a given config [key] with a given [value] via in Cloudflare DNS"
set config_key "$key.$CONFIG_DNS_DOMAIN"
set existing_id (
curl -X GET -s "https://api.cloudflare.com/client/v4/zones/$CF_API_ZONE/dns_records?name=contains:$config_key&type=TXT" \
-H "Authorization: Bearer $CF_API_KEY" \
-H "Content-Type: application/json" \
| jq -r '.result[0] | .id'
)
if [ "$existing_id" != "null" ]
curl -X DELETE -s "https://api.cloudflare.com/client/v4/zones/$CF_API_ZONE/dns_records/$existing_id" \
-H "Authorization: Bearer $CF_API_KEY" \
-H "Content-Type: application/json" | jq -r '.success' | grep true > /dev/null
end
curl -X POST -s "https://api.cloudflare.com/client/v4/zones/$CF_API_ZONE/dns_records" \
-H "Authorization: Bearer $CF_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"type": "TXT",
"name": "'"$config_key"'",
"content": "'"$value"'",
"ttl": '$CONFIG_DNS_TTL'
}' | jq -r '.success' | grep true > /dev/null
end
function get_secret --argument-names=key,passphrase --description "get a given config [key] with a given [default] from Cloudflare DNS"
get_config "$key" | aes_decrypt "$passphrase"
end
function set_secret --argument-names=key,value,passphrase --description "set a given config [key] with a given [value] via in Cloudflare DNS"
set_config "$key" (echo "$value | aes_encrypt "$passphrase")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment