def decrypt_token(token, _from): ''' Decrypt a token. ''' try: token_key = '{0}{1}'.format(hashlib.sha256(token).hexdigest(), _from) except Exception: raise TokenDecryptionError('Authentication error.') if token_key not in TOKENS: try: token = base64.b64decode(token) with stats.timer('kms_decrypt_token'): data = kms.decrypt( CiphertextBlob=token, EncryptionContext={ # This key is sent to us. 'to': app.config['AUTH_CONTEXT'], # From a service. 'from': _from }) # Decrypt doesn't take KeyId as an argument. We need to verify the # correct key was used to do the decryption. # Annoyingly, the KeyId from the data is actually an arn. key_arn = data['KeyId'] if key_arn != get_key_arn(app.config['AUTH_KEY']): raise TokenDecryptionError('Authentication error.') plaintext = data['Plaintext'] payload = json.loads(plaintext) # We don't care what exception is thrown. For paranoia's sake, fail # here. except Exception: log.exception('Failed to validate token.') raise TokenDecryptionError('Authentication error.') else: payload = TOKENS[token_key] time_format = "%Y%m%dT%H%M%SZ" now = datetime.datetime.utcnow() try: not_before = datetime.datetime.strptime(payload['not_before'], time_format) not_after = datetime.datetime.strptime(payload['not_after'], time_format) except Exception: log.exception( 'Failed to get not_before and not_after from token payload.') raise TokenDecryptionError('Authentication error.') delta = (not_after - not_before).seconds / 60 if delta > app.config['AUTH_TOKEN_MAX_LIFETIME']: log.warning('Token used which exceeds max token lifetime.') raise TokenDecryptionError('Authentication error.') if not (now >= not_before) and (now <= not_after): log.warning('Expired token used.') raise TokenDecryptionError('Authentication error.') TOKENS[token_key] = payload return payload
def grants_exist(service_name): try: role = iam.Role(name=service_name) role.load() except ClientError: return {'encrypt_grant': False, 'decrypt_grant': False} try: grants = get_grants() encrypt_grant, decrypt_grant = _grants_exist(role, grants) except ClientError: log.exception('Failed to get grants for {0}.'.format(service_name)) raise ServiceGetGrantError() return {'encrypt_grant': encrypt_grant, 'decrypt_grant': decrypt_grant}
def ensure_grants(service_name): ''' Add encryption and decryption grants for the service. TODO: We should probably orchestrate this, rather than doing it in confidant. ''' try: role = iam.Role(name=service_name) role.load() grants = get_grants() _ensure_grants(role, grants) except ClientError: log.exception('Failed to ensure grants for {0}.'.format(service_name)) raise ServiceCreateGrantError()
def grants_exist(service_name): try: role = iam.Role(name=service_name) role.load() except ClientError: return { 'encrypt_grant': False, 'decrypt_grant': False } try: grants = get_grants() encrypt_grant, decrypt_grant = _grants_exist(role, grants) except ClientError: log.exception('Failed to get grants for {0}.'.format(service_name)) raise ServiceGetGrantError() return { 'encrypt_grant': encrypt_grant, 'decrypt_grant': decrypt_grant }
def decrypt_token(token, _from): ''' Decrypt a token. ''' try: token_key = '{0}{1}'.format( hashlib.sha256(token).hexdigest(), _from ) except Exception: raise TokenDecryptionError('Authentication error.') if token_key not in TOKENS: try: token = base64.b64decode(token) with stats.timer('kms_decrypt_token'): data = kms.decrypt( CiphertextBlob=token, EncryptionContext={ # This key is sent to us. 'to': app.config['AUTH_CONTEXT'], # From a service. 'from': _from } ) # Decrypt doesn't take KeyId as an argument. We need to verify the # correct key was used to do the decryption. # Annoyingly, the KeyId from the data is actually an arn. key_arn = data['KeyId'] if key_arn != get_key_arn(app.config['AUTH_KEY']): raise TokenDecryptionError('Authentication error.') plaintext = data['Plaintext'] payload = json.loads(plaintext) # We don't care what exception is thrown. For paranoia's sake, fail # here. except Exception: log.exception('Failed to validate token.') raise TokenDecryptionError('Authentication error.') else: payload = TOKENS[token_key] time_format = "%Y%m%dT%H%M%SZ" now = datetime.datetime.utcnow() try: not_before = datetime.datetime.strptime( payload['not_before'], time_format ) not_after = datetime.datetime.strptime( payload['not_after'], time_format ) except Exception: log.exception( 'Failed to get not_before and not_after from token payload.' ) raise TokenDecryptionError('Authentication error.') delta = (not_after - not_before).seconds / 60 if delta > app.config['AUTH_TOKEN_MAX_LIFETIME']: log.warning('Token used which exceeds max token lifetime.') raise TokenDecryptionError('Authentication error.') if not (now >= not_before) and (now <= not_after): log.warning('Expired token used.') raise TokenDecryptionError('Authentication error.') TOKENS[token_key] = payload return payload