Use newer, less hacky ykman

This commit is contained in:
Jay Lee
2021-02-12 15:26:04 +00:00
parent 0fefa19f80
commit dff48e3146
2 changed files with 30 additions and 43 deletions

View File

@ -176,6 +176,11 @@ jobs:
run: | run: |
set +e set +e
$pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 $pip install -U --force-reinstall $pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 $pip install -U --force-reinstall
# install ykman from source to use latest with fewer deps
git clone https://github.com/Yubico/yubikey-manager.git
$pip install yubikey-manager/
$pip install --upgrade -r requirements.txt $pip install --upgrade -r requirements.txt
- name: Build GAM with PyInstaller - name: Build GAM with PyInstaller

View File

@ -1,69 +1,51 @@
import sys import sys
from threading import Timer from threading import Timer
# hack to avoid ImportError on unneccessary libraries from cryptography.hazmat.primitives import hashes
class fake_open(): from cryptography.hazmat.primitives.asymmetric import padding
open_devices = None from ykman.device import connect_to_device
sys.modules['ykman.driver_otp'] = fake_open from yubikit.piv import KEY_TYPE, SLOT, InvalidPinError, PivSession
from yubikit.core.smartcard import ApduError
import ykman.descriptor
# hack to avoid deprecation notice from cryptography
# remove after this lands:
# https://github.com/Yubico/yubikey-manager/pull/385
sys.modules['cryptography.utils'].int_from_bytes = int.from_bytes
from ykman.piv import SLOT, ALGO, PivController, DEFAULT_MANAGEMENT_KEY
from ykman.util import TRANSPORT
from gam import controlflow from gam import controlflow
class YubiKey(): class YubiKey():
def __init__(self, service_account_info): def __init__(self, service_account_info):
algo = service_account_info.get('yubikey_algo', 'RSA2048') key_type = service_account_info.get('yubikey_key_type', 'RSA2048')
try: try:
self.algo = getattr(ALGO, algo.upper()) self.key_type = getattr(KEY_TYPE, key_type.upper())
except AttributeError: except AttributeError:
controlflow.system_error_exit(6, f'{algo} is not a valid value for yubikey_algo') controlflow.system_error_exit(6, f'{key_type} is not a valid value for yubikey_key_type')
slot = service_account_info.get('yubikey_slot', 'AUTHENTICATION') slot = service_account_info.get('yubikey_slot', 'AUTHENTICATION')
try: try:
self.slot = getattr(SLOT, slot.upper()) self.slot = getattr(SLOT, slot.upper())
except AttributeError: except AttributeError:
controlflow.system_error_exit(6, f'{slot} is not a valid value for yubikey_slot') controlflow.system_error_exit(6, f'{slot} is not a valid value for yubikey_slot')
self.serial_number = service_account_info.get('yubikey_serial_number')
self.pin = service_account_info.get('yubikey_pin') self.pin = service_account_info.get('yubikey_pin')
self.key_id = service_account_info.get('private_key_id') self.key_id = service_account_info.get('private_key_id')
def touch_callback(self):
sys.stderr.write('\nTouch your YubiKey...\n')
def sign(self, message): def sign(self, message):
timer = Timer(0.5, self.touch_callback)
if 'mplock' in globals(): if 'mplock' in globals():
mplock.acquire() mplock.acquire()
try: try:
with ykman.descriptor.open_device(transports=TRANSPORT.CCID) as yk: conn, _, _ = connect_to_device(self.serial_number)
controller = PivController(yk.driver) session = PivSession(conn)
if self.pin: if self.pin:
controller.verify(self.pin)
timer.start() # if sign() takes more than .5 sec we need touch
try: try:
signed = controller.sign(self.slot, self.algo, message) session.verify_pin(self.pin)
except ykman.driver_ccid.APDUError: # We need PIN except InvalidPinError as err:
timer.cancel() # reset timer while user enters PIN controlflow.system_error_exit(7, f'YubiKey - {err}')
sys.stderr.write('\nEnter your YubiKey PIN:\n') try:
self.pin = input() signed = session.sign(slot=self.slot,
timer = Timer(0.5, self.touch_callback) key_type=self.key_type,
controller.verify(self.pin) message=message,
timer.start() hash_algorithm=hashes.SHA256(),
signed = controller.sign(self.slot, self.algo, message) padding=padding.PKCS1v15())
timer.cancel() except ApduError as err:
except ykman.descriptor.FailedOpeningDeviceException: controlflow.system_error_exit(8, f'YubiKey = {err}')
controlflow.system_error_exit(5, 'No YubiKey found. Is it plugged in?') except ValueError as err:
except ykman.piv.WrongPin: controlflow.system_error_exit(9, f'YubiKey - {err}')
controlflow.system_error_exit(7, 'Wrong PIN for YubiKey.')
except ykman.piv.AuthenticationBlocked:
controlflow.system_error_exit(8, 'YubiKey PIN is blocked.')
if 'mplock' in globals(): if 'mplock' in globals():
mplock.release() mplock.release()
return signed return signed