Fix broken key migration by decrypting legacy encrypted keys before LiteLLM update (#12657)

This commit is contained in:
Tim O'Farrell
2026-01-28 14:09:50 -08:00
committed by GitHub
parent d76ac44dc3
commit db6a9e8895
3 changed files with 25 additions and 20 deletions

View File

@@ -18,6 +18,7 @@ from server.constants import (
get_default_litellm_model,
)
from server.logger import logger
from storage.encrypt_utils import decrypt_legacy_value
from storage.user_settings import UserSettings
from openhands.server.settings import Settings
@@ -605,6 +606,13 @@ class LiteLlmManager:
logger.warning('LiteLLM API configuration not found')
return
try:
# Sometimes the key we get is encrypted - attempt to decrypt.
key = decrypt_legacy_value(key)
except Exception:
# The key was not encrypted
pass
payload = {
'key': key,
}
@@ -621,6 +629,7 @@ class LiteLlmManager:
'invalid_litellm_key_during_update',
extra={
'user_id': keycloak_user_id,
'text': response.text,
},
)
return

View File

@@ -420,7 +420,6 @@ class UserStore:
# For new sign-ups after migration, user_settings won't exist
# Fall back to getting data from org_members
is_new_signup = False
if not user_settings:
logger.info(
'user_store:downgrade_user:user_settings_not_found_checking_org_members',
@@ -443,7 +442,6 @@ class UserStore:
return None
org_member = org_members[0]
is_new_signup = True
# Create a new user_settings entry from OrgMember, User, and Org data
# This is needed for new sign-ups who don't have user_settings
@@ -465,27 +463,25 @@ class UserStore:
extra={'user_id': user_id},
)
# Get the API keys for LiteLLM downgrade
if is_new_signup:
# For new signups, we already have decrypted values in user_settings
decrypted_user_settings = user_settings
else:
# For migrated users, decrypt the legacy model
kwargs = decrypt_legacy_model(
[
'llm_api_key',
'llm_api_key_for_byor',
'search_api_key',
'sandbox_api_key',
],
user_settings,
)
decrypted_user_settings = UserSettings(**kwargs)
encrypted_fields = [
'llm_api_key',
'llm_api_key_for_byor',
'search_api_key',
'sandbox_api_key',
]
for field in encrypted_fields:
value = getattr(user_settings, field, None)
if value:
try:
value = decrypt_legacy_value(value)
setattr(user_settings, field, value)
except Exception:
pass
await LiteLlmManager.downgrade_entries(
str(org.id),
user_id,
decrypted_user_settings,
user_settings,
)
logger.debug(
'user_store:downgrade_user:done_litellm_downgrade_entries',

View File

@@ -654,7 +654,7 @@ class TestLiteLlmManager:
# Assert
mock_logger.warning.assert_called_once_with(
'invalid_litellm_key_during_update',
extra={'user_id': 'test-user-id'},
extra={'user_id': 'test-user-id', 'text': 'Unauthorized'},
)
@pytest.mark.asyncio