From 40b2fd09ffd9b3334b300765e71a46b76846d520 Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Wed, 4 Aug 2021 16:58:07 -0400 Subject: [PATCH] small service account improvements --- src/gam/__init__.py | 27 ++++++++++++++++----------- src/gam/auth/yubikey.py | 16 ++++++++++------ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/gam/__init__.py b/src/gam/__init__.py index a38b58b2..28b9c8da 100755 --- a/src/gam/__init__.py +++ b/src/gam/__init__.py @@ -1240,9 +1240,8 @@ def doCheckServiceAccount(users): 'get', name=name, throw_reasons=[gapi_errors.ErrorReason.FOUR_O_THREE]) - # Both Google and GAM set key valid after to day before creation key_created = dateutil.parser.parse( - key['validAfterTime'], ignoretz=True) + datetime.timedelta(days=1) + key['validAfterTime'], ignoretz=True) key_age = datetime.datetime.now() - key_created key_days = key_age.days if key_days > 30: @@ -7756,11 +7755,9 @@ def _generatePrivateKeyAndPublicCert(client_id, key_size): x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, client_id)])) builder = builder.issuer_name( x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, client_id)])) - not_valid_before = datetime.datetime.today() - datetime.timedelta(days=1) - not_valid_after = datetime.datetime.today() + datetime.timedelta( - days=365 * 10 - 1) - builder = builder.not_valid_before(not_valid_before) - builder = builder.not_valid_after(not_valid_after) + builder = builder.not_valid_before(datetime.datetime.today()) + # Google uses 12/31/9999 date for end time + builder = builder.not_valid_after(datetime.datetime(9999, 12, 31, 23, 59)) builder = builder.serial_number(x509.random_serial_number()) builder = builder.public_key(public_key) builder = builder.add_extension(x509.BasicConstraints(ca=False, @@ -7943,10 +7940,18 @@ def doCreateOrRotateServiceAccountKeys(iam=None, name=sa_name, body={'publicKeyData': publicKeyData}) break - except googleapiclient.errors.HttpError: - print('WARNING: that key already exists.') - result = {'name': oldPrivateKeyId} - break + except googleapiclient.errors.HttpError as err: + if hasattr(err, 'error_details') and \ + err.error_details == 'The given public key already exists.': + print('WARNING: that key already exists.') + result = {'name': oldPrivateKeyId} + break + elif hasattr(err, 'error_details'): + controlflow.system_error_exit( + 4, err.error_details) + else: + controlflow.system_error_exit( + 4, err) except gapi_errors.GapiNotFoundError as e: if i == max_retries: raise e diff --git a/src/gam/auth/yubikey.py b/src/gam/auth/yubikey.py index 43d95e75..e6a8ca9d 100644 --- a/src/gam/auth/yubikey.py +++ b/src/gam/auth/yubikey.py @@ -7,6 +7,7 @@ from threading import Timer from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding +from smartcard.Exceptions import CardConnectionException from ykman.device import connect_to_device from ykman.piv import generate_self_signed_certificate, \ generate_chuid @@ -46,7 +47,10 @@ class YubiKey(): self.key_id = service_account_info.get('private_key_id') def _connect(self): - conn, _, _ = connect_to_device(self.serial_number) + try: + conn, _, _ = connect_to_device(self.serial_number) + except CardConnectionException as err: + controlflow.system_error_exit(9, f'YubiKey - {err}') return conn def get_certificate(self): @@ -62,7 +66,7 @@ class YubiKey(): try: cert = session.get_certificate(self.slot) except ApduError as err: - controlflow.system_error_exit(9, f'Yubikey = {err}') + controlflow.system_error_exit(9, f'YubiKey - {err}') cert_pem = cert.public_bytes( serialization.Encoding.PEM).decode() publicKeyData = b64encode(cert_pem.encode()) @@ -78,7 +82,7 @@ class YubiKey(): _, _, info = connect_to_device(self.serial_number) return info.serial except ValueError as err: - controlflow.system_error_exit(9, f'YubikKey = {err}') + controlflow.system_error_exit(9, f'YubiKey - {err}') def reset_piv(self): '''Resets YubiKey PIV app and generates new key for GAM to use.''' @@ -101,7 +105,7 @@ class YubiKey(): DEFAULT_MANAGEMENT_KEY) piv.verify_pin(new_pin) - print('Yubikey is generating a non-exportable private key...') + print('YubiKey is generating a non-exportable private key...') pubkey = piv.generate_key(SLOT.AUTHENTICATION, KEY_TYPE.RSA2048, PIN_POLICY.ALWAYS, @@ -123,7 +127,7 @@ class YubiKey(): piv.put_object(OBJECT_ID.CHUID, generate_chuid()) except ValueError as err: - controlflow.system_error_exit(8, f'Yubikey - {err}') + controlflow.system_error_exit(8, f'YubiKey - {err}') def sign(self, message): @@ -145,7 +149,7 @@ class YubiKey(): hash_algorithm=hashes.SHA256(), padding=padding.PKCS1v15()) except ApduError as err: - controlflow.system_error_exit(8, f'YubiKey = {err}') + controlflow.system_error_exit(8, f'YubiKey - {err}') except ValueError as err: controlflow.system_error_exit(9, f'YubiKey - {err}') if 'mplock' in globals():