Created
January 13, 2020 03:21
-
-
Save philpennock/fc786f944d5bfa57991802c73e2efa1d to your computer and use it in GitHub Desktop.
CLI tool to unlock the XDG Secret collection used by 99designs/aws-vault
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# | |
# Copyright © 2020 Pennock Tech, LLC | |
# SPDX-License-Identifier: MIT | |
""" | |
aws-vault-unlock: unlock (or lock) the awsvault libsecret collection | |
The XDG folks specify the Secret service available over D-Bus. | |
When everything works right, 99designs/aws-vault trying to access a locked | |
collection automatically prompts for it to be unlocked. | |
When things do not work right, it's time to manually unlock it. | |
After which, even after locking it, automatic unlocking should happen. | |
You could also install Seahorse and use a GUI, but if you have more than | |
"a very small number" of OpenPGP keys on your system, then you will likely | |
regret that approach. | |
""" | |
__author__ = 'phil@pennock-tech.com (Phil Pennock)' | |
import argparse | |
import contextlib | |
import sys | |
try: | |
import secretstorage # pip: SecretStorage | |
except ModuleNotFoundError as e: | |
print(f'{e}\n Suggestion: pip install SecretStorage\n') | |
sys.exit(1) | |
DEF_COLLECTION_NAME = 'awsvault' | |
COLLECTION_PATH_PREFIX = '/org/freedesktop/secrets/collection/' | |
parser = argparse.ArgumentParser() | |
parser.add_argument('-l', '--lock', | |
action='store_true', default=False, | |
help='Lock secret collection/vault') | |
parser.add_argument('-u', '--unlock', | |
action='store_true', default=False, | |
help='Unlock secret collection/vault') | |
parser.add_argument('--list', | |
action='store_true', default=False, | |
help='List known collections') | |
parser.add_argument('--collection-name', | |
default=DEF_COLLECTION_NAME, | |
help='Collection alias to query [%(default)s]') | |
options = parser.parse_args() | |
if not (options.lock or options.unlock or options.list): | |
options.unlock = True | |
# Allow both unlock and lock: treat as desire to lock-then-unlock, bouncing | |
# the collection. Non-sensical perhaps, but do it. | |
with contextlib.closing(secretstorage.dbus_init()) as conn: | |
if options.list: | |
print('{:30} {:6} {}'.format('Collection', 'Locked', 'Path')) | |
LAYOUT='{!r:30} {:6} {!r}' | |
for collection in secretstorage.get_all_collections(conn): | |
print(LAYOUT.format(collection.get_label(), str(collection.is_locked()), collection.collection_path)) | |
sys.exit(0) | |
# collection = secretstorage.get_collection_by_alias(conn, options.collection_name) | |
# 'awsvault' is not an alias and I can find no way to look up a list of aliases, | |
# or any other introspection. Reading the 99designs/keyring Go code, they just iterate | |
# all the collections and look for a path match. | |
needle = COLLECTION_PATH_PREFIX + options.collection_name | |
candidates = [c for c in secretstorage.get_all_collections(conn) if c.collection_path == needle] | |
if len(candidates) == 0: | |
print(f'secret storage: collection {options.collection_name!r} NOT FOUND', file=sys.stderr) | |
sys.exit(1) | |
if len(candidates) > 1: | |
C = len(candidates) | |
print(f'secret storage: collection {options.collection_name!r} has {C} matches, assuming attack, aborting', file=sys.stderr) | |
sys.exit(1) | |
collection = candidates[0] | |
if options.lock: | |
if collection.is_locked(): | |
print(f'secret storage: collection {options.collection_name!r} was already locked', file=sys.stderr) | |
else: | |
collection.lock() | |
print(f'secret storage: collection {options.collection_name!r} now locked', file=sys.stderr) | |
if options.unlock: | |
if collection.is_locked(): | |
collection.unlock() | |
print(f'secret storage: collection {options.collection_name!r} now unlocked', file=sys.stderr) | |
else: | |
print(f'secret storage: collection {options.collection_name!r} was already unlocked', file=sys.stderr) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment