Skip to content

Instantly share code, notes, and snippets.

@dantman
Created December 18, 2022 01:18
Show Gist options
  • Save dantman/90747e8721d6555c5f975026e2df6456 to your computer and use it in GitHub Desktop.
Save dantman/90747e8721d6555c5f975026e2df6456 to your computer and use it in GitHub Desktop.
Utility for syncing credentials in WSL between aws-vault.exe and a Keepass database
import os, sys, re, shutil
from subprocess import check_call, CalledProcessError
AWS_VAULT_EXE = shutil.which('aws-vault.exe')
def process_entry(pw_entry):
if 'E' in pw_entry:
print(pw_entry['E'])
sys.exit(1)
if 'OK' in pw_entry:
return
if pw_entry.get('GRPN') != 'AWS Access Keys':
print(f"Skipping {pw_entry.get('GRPN', '?')}:{pw_entry['Title']}")
return
print(f"Importing profile {pw_entry['Title']} for {pw_entry['URL']}")
try:
check_call(
[
AWS_VAULT_EXE,
'add',
pw_entry['Title'],
'--env'
],
env={
'WSLENV': os.getenv('WSLENV') + ':AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY',
'AWS_ACCESS_KEY_ID': pw_entry['UserName'],
'AWS_SECRET_ACCESS_KEY': pw_entry['Password']
})
except CalledProcessError as e:
sys.exit(e.returncode)
raw_field_re = re.compile('^(\w+): (.+)$')
string_field_re = re.compile('^S: (\w+) = (.+)$')
current_entry = None
def add_field(key, value):
global current_entry
if not current_entry:
current_entry = {}
current_entry[key] = value
for line in sys.stdin.readlines():
line = line.rstrip()
if line == "":
if current_entry:
process_entry(current_entry)
current_entry = None
elif match := string_field_re.match(line):
add_field(match[1], match[2])
elif match := raw_field_re.match(line):
add_field(match[1], match[2])
else:
print("Unknown line encountered: " + line)
if current_entry:
process_entry(current_entry)
current_entry = None
# Utility for syncing credentials between aws-vault and Keepass
set -e
SCRIPTS="$(realpath "$( dirname -- "$0"; )")"
COMMAND="$1"
PROFILE="$2"
PROGRAMFILES="$(wslpath "$(wslvar PROGRAMFILES)")"
USERPROFILE="$(wslvar USERPROFILE)"
KPSCRIPT="$PROGRAMFILES/KeePass Password Safe 2/KPScript.exe"
KEEPASS_DB="$USERPROFILE\\Path\\To\\Your\\Keepass.kdbx"
case "$COMMAND" in
export)
if [ -z "$PROFILE" ]; then
echo "Profile not specified"
exit 1
fi
echo "Exporting $PROFILE from aws-vault to existing KeePass entry (use new if it does not exist)"
CREDENTIALS="$(aws-vault.exe exec "$PROFILE" --no-session --json)"
ACCESS_KEY_ID="$(echo "$CREDENTIALS" | jq -r '.AccessKeyId')"
SECRET_ACCESS_KEY="$(echo "$CREDENTIALS" | jq -r '.SecretAccessKey')"
CALLER_IDENTITY="$(env "AWS_ACCESS_KEY_ID=$ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY" aws sts get-caller-identity)"
CALLER_ARN="$(echo "$CALLER_IDENTITY" | jq -r '.Arn')"
echo "Saving access key for $CALLER_ARN to KeePass"
"$KPSCRIPT" -c:EditEntry "$KEEPASS_DB" --guikeyprompt \
-refx-Group:"AWS Access Keys" \
-ref-Title:"$PROFILE" \
-set-UserName:"$ACCESS_KEY_ID" \
-set-Password:"$SECRET_ACCESS_KEY" \
-set-URL:"$CALLER_ARN" \
-setx-Icon:30 \
;
;;
new)
if [ -z "$PROFILE" ]; then
echo "Profile not specified"
exit 1
fi
echo "Exporting $PROFILE from aws-vault to new KeePass entry"
CREDENTIALS="$(aws-vault.exe exec "$PROFILE" --no-session --json)"
ACCESS_KEY_ID="$(echo "$CREDENTIALS" | jq -r '.AccessKeyId')"
SECRET_ACCESS_KEY="$(echo "$CREDENTIALS" | jq -r '.SecretAccessKey')"
CALLER_IDENTITY="$(env "AWS_ACCESS_KEY_ID=$ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY" aws sts get-caller-identity)"
CALLER_ARN="$(echo "$CALLER_IDENTITY" | jq -r '.Arn')"
echo "Saving access key for $CALLER_ARN to KeePass"
;;
import)
echo "Importing profiles from KeePass into aws-vault"
"$KPSCRIPT" -c:ListEntries "$KEEPASS_DB" --guikeyprompt |
python3 "$SCRIPTS/aws-vault-sync-import.py"
;;
*)
echo "Unknown command, expected import, export, or new"
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment