bundlewrap-pass/bwpass.py

62 lines
1.7 KiB
Python

from os import environ
from os.path import expanduser
from subprocess import check_output, CalledProcessError
from bundlewrap.exceptions import FaultUnavailable
from bundlewrap.utils import Fault
from bundlewrap.utils.text import bold, yellow
from bundlewrap.utils.ui import io
PASSWORD_STORE_DIR = expanduser(environ.get('BW_PASS_DIR', '~/.password-store'))
DUMMY_MODE = environ.get('PW_PASS_DUMMY_MODE', '0') == '1'
cache = {}
def _get_contents_from_pass(identifier: str):
try:
return cache[identifier]
except KeyError:
# Not yet fetched from pass
pass
with io.job('{p} fetching {identifier}'.format(
p=bold('pass'),
identifier=identifier,
)):
try:
pass_output = check_output(
['pass', 'show', identifier],
env={
'PASSWORD_STORE_DIR': PASSWORD_STORE_DIR,
}
).decode('UTF-8').splitlines()
except FileNotFoundError:
raise FaultUnavailable('pass not found')
except CalledProcessError as e:
raise FaultUnavailable('pass exited {} when trying to get secret "{}"'.format(
e.returncode,
identifier,
))
cache[identifier] = {}
cache[identifier]['password'] = pass_output[0]
# TODO import all other options set in pass
return cache[identifier]
def _password(identifier):
if DUMMY_MODE:
return 'PASS DUMMY PASSWORD'
else:
secret = _get_contents_from_pass(identifier)
return secret['password']
def password(identifier):
return Fault(
'bwpass password',
_password,
identifier=identifier,
)