devai-api/app/api_utils.py (43 lines of code) (raw):

# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import logging import hmac from google.cloud import secretmanager from google.api_core.gapic_v1.client_info import ClientInfo from google.api_core.exceptions import NotFound, PermissionDenied from .constants import USER_AGENT def validate_api_key(api_key: str): """Validates an API key against the stored API key from Secret Manager. Args: api_key: The API key to validate. Returns: True if the API key is valid, False otherwise. """ devai_api_key = get_secret_value("DEVAI_API_KEY") if api_key is None or api_key == "" or devai_api_key is None: return False return is_valid_api_key(api_key, devai_api_key) def is_valid_api_key(passed_key, stored_key): """Compares an API key securely using hmac.compare_digest(). Args: passed_key: The API key to check, provided by the user. stored_key: The API key to validate against, retrieved from secure storage. Returns: True if the keys match, False otherwise. """ return hmac.compare_digest(passed_key.encode('utf-8'), stored_key.encode('utf-8')) def ensure_env_variable(var_name): """Ensures an environment variable is set. Args: var_name: The name of the environment variable to check. Returns: The value of the environment variable. Raises: EnvironmentError: If the environment variable is not set. """ value = os.getenv(var_name) if value is None: raise EnvironmentError(f"Required environment variable '{var_name}' is not set.") return value def get_secret_value( secret_id: str) -> str: """Retrieves a secret value from Google Secret Manager. Args: secret_id: The ID of the secret to retrieve. Returns: The secret value as a string, or None if the secret is not found or the user lacks permission. Raises: EnvironmentError: if PROJECT_ID is not defined. Exception: For any other unexpected error when getting the secret from the secret manager. """ try: project_id = ensure_env_variable('PROJECT_ID') logging.info("PROJECT_ID:", project_id) client = secretmanager.SecretManagerServiceClient( client_info=ClientInfo(user_agent=USER_AGENT) ) name = f"projects/{project_id}/secrets/{secret_id}/versions/latest" try: response = client.access_secret_version(name=name) payload = response.payload.data.decode("utf-8") logging.info(f"Successfully retrieved secret ID: {secret_id} in project {project_id}") return payload except PermissionDenied as e: logging.warning(f"Insufficient permissions to access secret {secret_id} in project {project_id}: {e}") return None except NotFound: logging.info(f"Secret ID not found: {secret_id} in project {project_id}") return None except Exception as e: # Catching a broader range of potential errors logging.error(f"An unexpected error occurred while retrieving secret '{secret_id}': {e}") return None except EnvironmentError as e: logging.error(e)