diff --git a/.circleci/config.yml b/.circleci/config.yml index 2653135da41..86d8c8eb127 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1706,6 +1706,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -1729,9 +1734,8 @@ jobs: command: | docker run -d \ -p 4001:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL="postgresql://postgres:postgres@host.docker.internal:5432/litellm_test" \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ --name schema-seed \ --add-host=host.docker.internal:host-gateway \ -v $(pwd)/litellm/proxy/example_config_yaml/simple_config.yaml:/app/config.yaml \ @@ -1802,6 +1806,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - attach_workspace: at: ~/project @@ -1825,9 +1834,8 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e USE_PRISMA_MIGRATE=True \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e AZURE_API_KEY=$AZURE_API_KEY \ @@ -1872,7 +1880,7 @@ jobs: name: Seed the routing strategy through /config/update command: | curl --noproxy '*' -sSf -X POST http://localhost:4000/config/update \ - -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' \ -d '{"router_settings": {"routing_strategy": "usage-based-routing-v2"}}' - run: name: Run tests @@ -1901,6 +1909,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -1922,9 +1935,8 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e AZURE_API_KEY=$AZURE_API_KEY \ -e AZURE_API_BASE=$AZURE_API_BASE \ -e AZURE_API_VERSION="2024-05-01-preview" \ @@ -1987,6 +1999,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -2012,12 +2029,11 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e REDIS_HOST=$REDIS_HOST \ -e REDIS_PASSWORD=$REDIS_PASSWORD \ -e REDIS_PORT=$REDIS_PORT \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ @@ -2073,12 +2089,11 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e REDIS_HOST=$REDIS_HOST \ -e REDIS_PASSWORD=$REDIS_PASSWORD \ -e REDIS_PORT=$REDIS_PORT \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE="bad-license" \ @@ -2122,6 +2137,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -2151,11 +2171,10 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e REDIS_HOST=host.docker.internal \ -e REDIS_PORT=6379 \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ @@ -2210,6 +2229,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -2234,12 +2258,11 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e REDIS_HOST=$REDIS_HOST \ -e REDIS_PASSWORD=$REDIS_PASSWORD \ -e REDIS_PORT=$REDIS_PORT \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ -e USE_DDTRACE=True \ @@ -2257,12 +2280,11 @@ jobs: command: | docker run -d \ -p 4001:4001 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e REDIS_HOST=$REDIS_HOST \ -e REDIS_PASSWORD=$REDIS_PASSWORD \ -e REDIS_PORT=$REDIS_PORT \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ -e USE_DDTRACE=True \ @@ -2309,6 +2331,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -2335,10 +2362,9 @@ jobs: docker run -d \ --restart on-failure \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e STORE_MODEL_IN_DB="True" \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e TEAM_METADATA_VALIDATION_SERVICE_URL=http://host.docker.internal:9414/validate \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ @@ -2388,6 +2414,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns # Remove Docker CLI installation since it's already available in machine executor @@ -2410,12 +2441,11 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e REDIS_HOST=$REDIS_HOST \ -e REDIS_PASSWORD=$REDIS_PASSWORD \ -e REDIS_PORT=$REDIS_PORT \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ @@ -2472,6 +2502,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -2493,9 +2528,8 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ -e GEMINI_API_KEY=$GEMINI_API_KEY \ -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \ @@ -2563,6 +2597,11 @@ jobs: working_directory: ~/project steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes - setup_google_dns - install_uv @@ -2585,9 +2624,8 @@ jobs: command: | docker run -d \ -p 4000:4000 \ - -e LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ - -e LITELLM_MASTER_KEY="sk-1234" \ + -e LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" \ -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \ -e RECORDER_ANTHROPIC_BASE_URL=http://host.docker.internal:8090/__recorder_upstream/api.anthropic.com \ -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ @@ -2613,7 +2651,7 @@ jobs: command: | mkdir -p test-results export LITELLM_PROXY_URL="http://localhost:4000" - export LITELLM_API_KEY="sk-1234" + export LITELLM_API_KEY="$LITELLM_MASTER_KEY" TEST_FILES=$(circleci tests glob "tests/proxy_e2e_anthropic_messages_tests/**/test_*.py") echo "$TEST_FILES" | circleci tests run \ --verbose \ @@ -2676,6 +2714,11 @@ jobs: PROXY_LOGOUT_URL: "https://www.example.com" steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes: category: client - setup_google_dns @@ -2766,8 +2809,6 @@ jobs: - run: name: Start LiteLLM proxy environment: - LITELLM_MASTER_KEY: "sk-1234" - LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY: "true" MOCK_LLM_URL: "http://127.0.0.1:8090/v1" DISABLE_SCHEMA_UPDATE: "true" SERVER_ROOT_PATH: "" @@ -2787,7 +2828,7 @@ jobs: name: Wait for proxy to be ready command: | for i in $(seq 1 60); do - HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:4000/health -H "Authorization: Bearer sk-1234" 2>/dev/null || true) + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:4000/health -H "Authorization: Bearer $LITELLM_MASTER_KEY" 2>/dev/null || true) if [ "$HTTP_CODE" = "200" ]; then echo "Proxy is ready" exit 0 @@ -2834,6 +2875,11 @@ jobs: SERVER_ROOT_PATH: "/litellm" steps: - checkout + - run: + name: Generate LiteLLM master key + command: | + key="$(openssl rand -hex 16)" + printf 'export LITELLM_MASTER_KEY=sk-%s\n' "$key" >> "$BASH_ENV" - skip_if_unrelated_changes: category: client - setup_google_dns @@ -2910,8 +2956,6 @@ jobs: - run: name: Start LiteLLM proxy under a server root path environment: - LITELLM_MASTER_KEY: "sk-1234" - LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY: "true" MOCK_LLM_URL: "http://127.0.0.1:8090/v1" DISABLE_SCHEMA_UPDATE: "true" # Output flows to this step's own log, so a boot crash is visible here @@ -2926,7 +2970,7 @@ jobs: name: Wait for prefixed proxy to be ready command: | for i in $(seq 1 60); do - HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 -H "Authorization: Bearer sk-1234" http://127.0.0.1:4000/litellm/health 2>/dev/null || true) + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 -H "Authorization: Bearer $LITELLM_MASTER_KEY" http://127.0.0.1:4000/litellm/health 2>/dev/null || true) if [ "$HTTP_CODE" = "200" ]; then echo "Prefixed proxy is ready" exit 0 diff --git a/.circleci/scripts/run_integration.sh b/.circleci/scripts/run_integration.sh index c03220224d2..90a6184d8a0 100644 --- a/.circleci/scripts/run_integration.sh +++ b/.circleci/scripts/run_integration.sh @@ -72,7 +72,7 @@ export PATH="$PWD/.venv/bin:$PATH" export PYTHONPATH="$PWD:$PWD/tests:$PWD/tests/e2e" export DATABASE_URL="postgresql://postgres:postgres@127.0.0.1:5432/circle_test" export REDIS_HOST=127.0.0.1 REDIS_PORT=6379 -export LITELLM_MASTER_KEY=sk-integration-master LITELLM_SALT_KEY=sk-integration-salt +export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 16)" LITELLM_SALT_KEY=sk-integration-salt export LITELLM_MODE=PRODUCTION LITELLM_LOCAL_MODEL_COST_MAP=True export STORE_MODEL_IN_DB=True AWS_EC2_METADATA_DISABLED=true DO_NOT_TRACK=1 export INTEGRATION_PROXY_URL=http://127.0.0.1:4000 diff --git a/.gitguardian.yaml b/.gitguardian.yaml index 2a16ffe0c52..0e436ebd209 100644 --- a/.gitguardian.yaml +++ b/.gitguardian.yaml @@ -84,10 +84,6 @@ secret: - name: Langfuse test credentials in test_completion match: c39310f68cc3d3e22f7b298bb6353c4f45759adcc37080d8b7f4e535d3cfd7f4 - # Test password "sk-1234" in e2e test fixtures - test fixture, not a real secret - - name: Test password in e2e test fixtures - match: ce32b547202e209ec1dd50107b64be4cfcf2eb15c3b4f8e9dc611ef747af634f - # === Preventive patterns for test keys (pattern-based) === # Test API keys (124 instances across 45 files) @@ -108,4 +104,3 @@ secret: - name: Short fake sk keys (1–9 digits only) match: \bsk-\d{1,9}\b - diff --git a/.github/PULL_REQUEST_TEMPLATE/general.md b/.github/PULL_REQUEST_TEMPLATE/general.md index 6beb6e99e0e..d9e72d58632 100644 --- a/.github/PULL_REQUEST_TEMPLATE/general.md +++ b/.github/PULL_REQUEST_TEMPLATE/general.md @@ -150,7 +150,7 @@ For each e2e test you added or changed, list the manual steps a reviewer can fol Example checklists: - tests/e2e/quota_management/ratelimit/test_rate_limit_e2e.py::TestKeyRateLimits::test_rpm_limit_blocks_over_limit - a key allowed 2 requests a minute serves exactly 2 and refuses the 3rd - - [ ] Generate a limited key: curl -X POST http://localhost:4000/key/generate -H "Authorization: Bearer sk-1234" -d '{"rpm_limit": 2}' + - [ ] Generate a limited key: curl -X POST http://localhost:4000/key/generate -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{"rpm_limit": 2}' - [ ] Send three /v1/chat/completions requests with that key inside one minute - [ ] Expect the first two to return 200 and the third to return 429 naming the rpm limit - [ ] Sanity check: this test makes sense to add and is not hand-wavey (e.g., assert actual expected spend instead of just spend > 0) or potentially flaky @@ -164,4 +164,3 @@ Example checklists: ## Final Attestation - [ ] The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR - diff --git a/.github/workflows/test-code-quality.yml b/.github/workflows/test-code-quality.yml index 004de9c759b..ef38220ca49 100644 --- a/.github/workflows/test-code-quality.yml +++ b/.github/workflows/test-code-quality.yml @@ -95,7 +95,9 @@ jobs: - name: test_e2e_metadata env: PYTHONPATH: tests/e2e - run: uv run --no-sync pytest -q --noconftest -p no:cacheprovider -c /dev/null tests/code_coverage_tests/test_e2e_metadata.py tests/code_coverage_tests/test_e2e_junit_report.py + run: | + export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 16)" + uv run --no-sync pytest -q --noconftest -p no:cacheprovider -c /dev/null tests/code_coverage_tests/test_e2e_metadata.py tests/code_coverage_tests/test_e2e_junit_report.py - name: Check merge smoke harness run: uv run --no-sync pytest -q --noconftest -p no:cacheprovider -c /dev/null tests/code_coverage_tests/test_merge_smoke.py @@ -163,6 +165,9 @@ jobs: - name: check_migrations_no_data_rewrites run: uv run --no-sync python ./tests/code_coverage_tests/check_migrations_no_data_rewrites.py + - name: check_no_publicly_known_master_key + run: uv run --no-sync python ./tests/code_coverage_tests/check_no_publicly_known_master_key.py + - name: check_unbounded_in_lists (fails on findings not in the baseline) run: uv run --no-sync python ./tests/code_coverage_tests/check_unbounded_in_lists.py diff --git a/ci_cd/TEST_KEY_PATTERNS.md b/ci_cd/TEST_KEY_PATTERNS.md index bd59f582839..aada8608397 100644 --- a/ci_cd/TEST_KEY_PATTERNS.md +++ b/ci_cd/TEST_KEY_PATTERNS.md @@ -5,7 +5,7 @@ Standard patterns for test/mock keys and credentials in the LiteLLM codebase to ## How GitGuardian Works GitGuardian uses **machine learning and entropy analysis**, not just pattern matching: -- **Low entropy** values (like `sk-1234`, `postgres`) are automatically ignored +- **Low entropy** values (like `sk-test`, `postgres`) are automatically ignored - **High entropy** values (realistic-looking secrets) trigger detection - **Context-aware** detection understands code syntax like `os.environ["KEY"]` @@ -15,8 +15,8 @@ GitGuardian uses **machine learning and entropy analysis**, not just pattern mat These won't trigger GitGuardian's ML detector: ```python -api_key = "sk-1234" -api_key = "sk-12345" +api_key = "sk-test" +api_key = "sk-mock" database_password = "postgres" token = "test123" ``` diff --git a/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb b/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb index 740e7c7a4c8..d89f2b67c56 100644 --- a/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb +++ b/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb @@ -16,6 +16,8 @@ "\n", "These are **selected examples**. LiteLLM Proxy is **OpenAI-Compatible**, it works with any project that calls OpenAI. Just change the `base_url`, `api_key` and `model`.\n", "\n", + "Set `LITELLM_MASTER_KEY` in the notebook environment to the same key configured on the proxy before running authenticated examples\n", + "\n", "For more examples, [go here](https://docs.litellm.ai/docs/proxy/user_keys)\n", "\n", "To pass provider-specific args, [go here](https://docs.litellm.ai/docs/completion/provider_specific_params#proxy-usage)\n", @@ -95,9 +97,10 @@ }, "outputs": [], "source": [ + "import os\n", "from openai import OpenAI\n", "client = OpenAI(\n", - " api_key=\"sk-1234\", # [OPTIONAL] set if you set one on proxy, else set \"\"\n", + " api_key=os.environ[\"LITELLM_MASTER_KEY\"],\n", " base_url=\"http://0.0.0.0:4000\",\n", ")\n", "\n", @@ -298,14 +301,14 @@ " engine=\"azure-gpt-3.5\", # model_name on litellm proxy\n", " temperature=0.0,\n", " azure_endpoint=\"http://0.0.0.0:4000\", # litellm proxy endpoint\n", - " api_key=\"sk-1234\", # litellm proxy API Key\n", + " api_key=os.environ[\"LITELLM_MASTER_KEY\"],\n", " api_version=\"2023-07-01-preview\",\n", ")\n", "\n", "embed_model = AzureOpenAIEmbedding(\n", " deployment_name=\"azure-embedding-model\",\n", " azure_endpoint=\"http://0.0.0.0:4000\",\n", - " api_key=\"sk-1234\",\n", + " api_key=os.environ[\"LITELLM_MASTER_KEY\"],\n", " api_version=\"2023-07-01-preview\",\n", ")\n", "\n", @@ -341,7 +344,7 @@ "\n", "const model = new ChatOpenAI({\n", " modelName: \"gpt-4\",\n", - " openAIApiKey: \"sk-1234\",\n", + " openAIApiKey: process.env.LITELLM_MASTER_KEY,\n", " modelKwargs: {\"metadata\": \"hello world\"} // 👈 PASS Additional params here\n", "}, {\n", " basePath: \"http://0.0.0.0:4000\",\n", @@ -372,7 +375,7 @@ "const { OpenAI } = require('openai');\n", "\n", "const openai = new OpenAI({\n", - " apiKey: \"sk-1234\", // This is the default and can be omitted\n", + " apiKey: process.env.LITELLM_MASTER_KEY,\n", " baseURL: \"http://0.0.0.0:4000\"\n", "});\n", "\n", diff --git a/cookbook/Proxy_Batch_Users.ipynb b/cookbook/Proxy_Batch_Users.ipynb index c362ab8f8a2..bd18de5e988 100644 --- a/cookbook/Proxy_Batch_Users.ipynb +++ b/cookbook/Proxy_Batch_Users.ipynb @@ -6,7 +6,9 @@ "id": "680oRk1af-xJ" }, "source": [ - "# Environment Setup" + "# Environment Setup\n", + "\n", + "Set `LITELLM_MASTER_KEY` in the notebook environment to the same key configured on the proxy before running the cells" ] }, { @@ -17,6 +19,7 @@ }, "outputs": [], "source": [ + "import os\n", "import csv\n", "from typing import Optional\n", "import httpx\n", @@ -24,7 +27,7 @@ "import asyncio\n", "\n", "proxy_base_url = \"http://0.0.0.0:4000\" # 👈 SET TO PROXY URL\n", - "master_key = \"sk-1234\" # 👈 SET TO PROXY MASTER KEY" + "master_key = os.environ[\"LITELLM_MASTER_KEY\"]" ] }, { diff --git a/cookbook/ai_coding_tool_guides/claude_code_quickstart/guide.md b/cookbook/ai_coding_tool_guides/claude_code_quickstart/guide.md index b2d81be25bb..cd27eed18a3 100644 --- a/cookbook/ai_coding_tool_guides/claude_code_quickstart/guide.md +++ b/cookbook/ai_coding_tool_guides/claude_code_quickstart/guide.md @@ -47,7 +47,7 @@ Set your environment variables: ```bash export ANTHROPIC_API_KEY="your-anthropic-api-key" -export LITELLM_MASTER_KEY="sk-1234567890" # Generate a secure key +export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 32)" ``` ## Step 2: Start Proxy @@ -292,4 +292,3 @@ model_list: - [LiteLLM Documentation](https://docs.litellm.ai/) - [Claude Code Documentation](https://docs.anthropic.com/en/docs/claude-code/overview) - [Anthropic's LiteLLM Configuration Guide](https://docs.anthropic.com/en/docs/claude-code/llm-gateway#litellm-configuration) - diff --git a/cookbook/anthropic_agent_sdk/README.md b/cookbook/anthropic_agent_sdk/README.md index 294d949e24e..4521aee310a 100644 --- a/cookbook/anthropic_agent_sdk/README.md +++ b/cookbook/anthropic_agent_sdk/README.md @@ -20,6 +20,12 @@ litellm --model claude-sonnet-4-20250514 litellm --config config.yaml ``` +Generate a master key before starting the proxy: + +```bash +export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 32)" +``` + ### 3. Run the chat **Basic Agent (no MCP):** @@ -58,7 +64,7 @@ Set these environment variables if needed: ```bash export LITELLM_PROXY_URL="http://localhost:4000" -export LITELLM_API_KEY="sk-1234" +export LITELLM_API_KEY="$LITELLM_MASTER_KEY" export LITELLM_MODEL="bedrock-claude-sonnet-4.5" ``` @@ -98,7 +104,7 @@ The key is pointing the Agent SDK to LiteLLM instead of directly to Anthropic: ```python # Point to LiteLLM gateway (not Anthropic) os.environ["ANTHROPIC_BASE_URL"] = "http://localhost:4000" -os.environ["ANTHROPIC_API_KEY"] = "sk-1234" # Your LiteLLM key +os.environ["ANTHROPIC_API_KEY"] = os.environ["LITELLM_API_KEY"] # Use any model configured in LiteLLM options = ClaudeAgentOptions( diff --git a/cookbook/anthropic_agent_sdk/common.py b/cookbook/anthropic_agent_sdk/common.py index a2555ed3372..505b5ecd91c 100644 --- a/cookbook/anthropic_agent_sdk/common.py +++ b/cookbook/anthropic_agent_sdk/common.py @@ -13,7 +13,7 @@ class Config: LITELLM_PROXY_URL = os.getenv("LITELLM_PROXY_URL", "http://localhost:4000") # LiteLLM API key (master key or virtual key) - LITELLM_API_KEY = os.getenv("LITELLM_API_KEY", "sk-1234") + LITELLM_API_KEY = os.environ["LITELLM_API_KEY"] # Model name as configured in LiteLLM (e.g., "bedrock-claude-sonnet-4", "gpt-4", etc.) LITELLM_MODEL = os.getenv("LITELLM_MODEL", "bedrock-claude-sonnet-4.5") diff --git a/cookbook/litellm_proxy_server/batch_api/bedrock/bedrock.py b/cookbook/litellm_proxy_server/batch_api/bedrock/bedrock.py index b5117ab9eeb..5b5f0978eb3 100644 --- a/cookbook/litellm_proxy_server/batch_api/bedrock/bedrock.py +++ b/cookbook/litellm_proxy_server/batch_api/bedrock/bedrock.py @@ -1,8 +1,10 @@ +import os + from openai import OpenAI client = OpenAI( base_url="http://0.0.0.0:4000", - api_key="sk-1234", + api_key=os.environ["LITELLM_MASTER_KEY"], ) BEDROCK_BATCH_MODEL = "bedrock/batch-anthropic.claude-3-5-sonnet-20240620-v1:0" diff --git a/cookbook/litellm_proxy_server/mcp/mcp_with_litellm_proxy.py b/cookbook/litellm_proxy_server/mcp/mcp_with_litellm_proxy.py index cc93302761d..cc8b44d42b0 100644 --- a/cookbook/litellm_proxy_server/mcp/mcp_with_litellm_proxy.py +++ b/cookbook/litellm_proxy_server/mcp/mcp_with_litellm_proxy.py @@ -4,10 +4,12 @@ Use LiteLLM Proxy MCP Gateway to call MCP tools. When using LiteLLM Proxy, you can use the same MCP tools across all your LLM providers. """ +import os + import openai client = openai.OpenAI( - api_key="sk-1234", # paste your litellm proxy api key here + api_key=os.environ["LITELLM_MASTER_KEY"], base_url="http://localhost:4000", # paste your litellm proxy base url here ) print("Making API request to Responses API with MCP tools") diff --git a/cookbook/livekit_agent_sdk/README.md b/cookbook/livekit_agent_sdk/README.md index 1c3f0bf9564..6c794165e96 100644 --- a/cookbook/livekit_agent_sdk/README.md +++ b/cookbook/livekit_agent_sdk/README.md @@ -15,12 +15,14 @@ pip install livekit-agents[xai] websockets ```bash # With xAI export XAI_API_KEY="your-xai-key" +export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 32)" litellm --config config.yaml --port 4000 ``` ### 3. Run the voice agent ```bash +export LITELLM_API_KEY="$LITELLM_MASTER_KEY" python main.py ``` @@ -32,7 +34,7 @@ Set these environment variables if needed: ```bash export LITELLM_PROXY_URL="http://localhost:4000" -export LITELLM_API_KEY="sk-1234" +export LITELLM_API_KEY="$LITELLM_MASTER_KEY" export LITELLM_MODEL="grok-voice-agent" ``` @@ -59,7 +61,7 @@ model_list: mode: realtime general_settings: - master_key: sk-1234 + master_key: os.environ/LITELLM_MASTER_KEY ``` Then start: `litellm --config config.yaml --port 4000` @@ -73,7 +75,7 @@ from livekit.plugins import xai model = xai.realtime.RealtimeModel( voice="ara", - api_key="sk-1234", # LiteLLM proxy key + api_key=os.environ["LITELLM_MASTER_KEY"], base_url="http://localhost:4000", # Point to LiteLLM ) ``` diff --git a/cookbook/livekit_agent_sdk/config.example.yaml b/cookbook/livekit_agent_sdk/config.example.yaml index 072625018a7..388aa24f501 100644 --- a/cookbook/livekit_agent_sdk/config.example.yaml +++ b/cookbook/livekit_agent_sdk/config.example.yaml @@ -17,4 +17,4 @@ litellm_settings: drop_params: True general_settings: - master_key: sk-1234 # Change this to a secure key + master_key: os.environ/LITELLM_MASTER_KEY diff --git a/cookbook/livekit_agent_sdk/main.py b/cookbook/livekit_agent_sdk/main.py index c68e5534ea8..fdc72e518b4 100644 --- a/cookbook/livekit_agent_sdk/main.py +++ b/cookbook/livekit_agent_sdk/main.py @@ -13,7 +13,7 @@ import websockets # Configuration PROXY_URL = os.getenv("LITELLM_PROXY_URL", "http://localhost:4000") -API_KEY = os.getenv("LITELLM_API_KEY", "sk-1234") +API_KEY = os.environ["LITELLM_API_KEY"] MODEL = os.getenv("LITELLM_MODEL", "grok-voice-agent") diff --git a/cookbook/misc/config.yaml b/cookbook/misc/config.yaml index a485bf825fc..8ad1d764af5 100644 --- a/cookbook/misc/config.yaml +++ b/cookbook/misc/config.yaml @@ -58,7 +58,7 @@ litellm_settings: context_window_fallbacks: [{"gpt-3.5-turbo": ["gpt-3.5-turbo-large"]}] general_settings: - master_key: sk-1234 # [OPTIONAL] Use to enforce auth on proxy. See - https://docs.litellm.ai/docs/proxy/virtual_keys + master_key: os.environ/LITELLM_MASTER_KEY store_model_in_db: True proxy_budget_rescheduler_min_time: 60 proxy_budget_rescheduler_max_time: 64 diff --git a/cookbook/misc/migrate_proxy_config.py b/cookbook/misc/migrate_proxy_config.py index 31c3f32c08a..b15f9663c64 100644 --- a/cookbook/misc/migrate_proxy_config.py +++ b/cookbook/misc/migrate_proxy_config.py @@ -12,6 +12,8 @@ Step 2: reads `model_list` and loops through all models Step 3: calls `/model/new` for each model """ +import os + import yaml import requests @@ -89,7 +91,7 @@ def migrate_models(config_file, proxy_base_url): # Usage config_file = "config.yaml" proxy_base_url = "http://0.0.0.0:4000" -master_key = "sk-1234" +master_key = os.environ["LITELLM_MASTER_KEY"] print(f"config_file: {config_file}") print(f"proxy_base_url: {proxy_base_url}") migrate_models(config_file, proxy_base_url) diff --git a/cookbook/misc/test_responses_api.py b/cookbook/misc/test_responses_api.py index 68da5fb6cd0..7abf3170fbc 100644 --- a/cookbook/misc/test_responses_api.py +++ b/cookbook/misc/test_responses_api.py @@ -1,8 +1,10 @@ import base64 +import os + from openai import OpenAI import time -client = OpenAI(base_url="http://0.0.0.0:4001", api_key="sk-1234") +client = OpenAI(base_url="http://0.0.0.0:4001", api_key=os.environ["LITELLM_MASTER_KEY"]) # Function to encode the image diff --git a/cookbook/mlflow_langchain_tracing_litellm_proxy.ipynb b/cookbook/mlflow_langchain_tracing_litellm_proxy.ipynb index 1aca0e13c87..818a25e4503 100644 --- a/cookbook/mlflow_langchain_tracing_litellm_proxy.ipynb +++ b/cookbook/mlflow_langchain_tracing_litellm_proxy.ipynb @@ -4,7 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Databricks Notebook with MLFlow AutoLogging for LiteLLM Proxy calls\n" + "# Databricks Notebook with MLFlow AutoLogging for LiteLLM Proxy calls\n", + "\n", + "Set `LITELLM_PROXY_API_KEY` in the notebook environment to a key accepted by the proxy before running the model cell\n" ] }, { @@ -160,11 +162,13 @@ }, "outputs": [], "source": [ + "import os\n", + "\n", "model = ChatOpenAI(\n", " openai_api_base=\"LITELLM_PROXY_BASE_URL\", # e.g.: http://0.0.0.0:4000\n", " model = \"gpt-3.5-turbo\", # LITELLM 'model_name'\n", " temperature=0.1, \n", - " api_key=\"LITELLM_PROXY_API_KEY\" # e.g.: \"sk-1234\"\n", + " api_key=os.environ[\"LITELLM_PROXY_API_KEY\"]\n", ")" ] }, diff --git a/cookbook/mock_prompt_management_server/README.md b/cookbook/mock_prompt_management_server/README.md index 9ec76baacf7..c13061cfe89 100644 --- a/cookbook/mock_prompt_management_server/README.md +++ b/cookbook/mock_prompt_management_server/README.md @@ -69,7 +69,7 @@ litellm --config config.yaml ```bash curl http://0.0.0.0:4000/v1/chat/completions \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-3.5-turbo", "prompt_id": "hello-world-prompt", @@ -290,4 +290,3 @@ Before deploying to production: ## Questions? This is a reference implementation for the LiteLLM Generic Prompt Management API. For questions or issues, please open an issue on the [LiteLLM GitHub repository](https://github.com/BerriAI/litellm). - diff --git a/cookbook/nova_sonic_realtime.py b/cookbook/nova_sonic_realtime.py index ab510556254..50844121cbf 100644 --- a/cookbook/nova_sonic_realtime.py +++ b/cookbook/nova_sonic_realtime.py @@ -10,6 +10,7 @@ Prerequisites: - websockets installed: pip install websockets Usage: + export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 32)" python nova_sonic_realtime.py """ @@ -33,7 +34,7 @@ CHUNK_SIZE = 1024 # LiteLLM proxy configuration LITELLM_PROXY_URL = "ws://localhost:4000/v1/realtime?model=bedrock-sonic" -LITELLM_API_KEY = "sk-12345" # Your LiteLLM API key +LITELLM_API_KEY = os.environ["LITELLM_MASTER_KEY"] class RealtimeClient: diff --git a/cookbook/veo_video_generation.py b/cookbook/veo_video_generation.py index 4df2d946a01..8587032e0be 100644 --- a/cookbook/veo_video_generation.py +++ b/cookbook/veo_video_generation.py @@ -24,8 +24,8 @@ class VeoVideoGenerator: def __init__( self, + api_key: str, base_url: str = "http://localhost:4000/gemini/v1beta", - api_key: str = "sk-1234", ): """ Initialize the Veo video generator. @@ -274,12 +274,12 @@ def main(): Configure these environment variables: - LITELLM_BASE_URL: Your LiteLLM proxy URL (default: http://localhost:4000/gemini/v1beta) - - LITELLM_API_KEY: Your LiteLLM API key (default: sk-1234) + - LITELLM_API_KEY: API key for LiteLLM proxy authentication """ # Configuration from environment or defaults base_url = os.getenv("LITELLM_BASE_URL", "http://localhost:4000/gemini/v1beta") - api_key = os.getenv("LITELLM_API_KEY", "sk-1234") + api_key = os.environ["LITELLM_API_KEY"] print("🚀 Starting Veo Video Generation Example") print(f"📡 Using LiteLLM proxy at: {base_url}") diff --git a/deploy/lens/README.md b/deploy/lens/README.md index 2b0914c2c7f..43f078dbcb5 100644 --- a/deploy/lens/README.md +++ b/deploy/lens/README.md @@ -21,7 +21,7 @@ docker build --build-arg LITELLM_RELEASE_TAG="$LITELLM_RELEASE_TAG" \ docker compose -f docker/docker-compose.tracing.yml up -d --build ``` -Open `http://localhost:4002/ui/` and sign in as `admin` with password `sk-1234`. Go to **Lens > Investigations > Connect worker**, choose a model and monthly budget, then **Get install command**. Expand **Using Docker Compose or Helm?** and copy the worker token. In the same terminal, run: +Open `http://localhost:4002/ui/` and sign in as `admin` with the key saved in `.lens-dev/master_key`. Go to **Lens > Investigations > Connect worker**, choose a model and monthly budget, then **Get install command**. Expand **Using Docker Compose or Helm?** and copy the worker token. In the same terminal, run: ```bash export LITELLM_URL=http://litellm:4000 diff --git a/docker/docker-compose.tracing.yml b/docker/docker-compose.tracing.yml index c8d90fbc0ae..87d7197725e 100644 --- a/docker/docker-compose.tracing.yml +++ b/docker/docker-compose.tracing.yml @@ -9,8 +9,7 @@ services: LITELLM_RELEASE_TAG: ${LITELLM_RELEASE_TAG:-} command: ["--config", "/app/tracing-config.yaml", "--port", "4000"] environment: - LITELLM_MASTER_KEY: sk-1234 - LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY: "true" + LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY:?set LITELLM_MASTER_KEY} LITELLM_SALT_KEY: sk-local-tracing-salt-key DATABASE_URL: postgresql://litellm:litellm@db:5432/litellm STORE_MODEL_IN_DB: "True" diff --git a/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py b/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py index 313867bbec4..eb1cd27abe9 100644 --- a/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py +++ b/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py @@ -433,7 +433,7 @@ async def new_project( ```bash curl --location 'http://0.0.0.0:4000/project/new' \\ - --header 'Authorization: Bearer sk-1234' \\ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \\ --header 'Content-Type: application/json' \\ --data '{ "project_alias": "flight-search-assistant", @@ -460,7 +460,7 @@ async def new_project( ```bash curl --location 'http://0.0.0.0:4000/project/new' \\ - --header 'Authorization: Bearer sk-1234' \\ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \\ --header 'Content-Type: application/json' \\ --data '{ "project_alias": "hotel-recommendations", @@ -648,7 +648,7 @@ async def update_project( Example: ```bash curl --location 'http://0.0.0.0:4000/project/update' \\ - --header 'Authorization: Bearer sk-1234' \\ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \\ --header 'Content-Type: application/json' \\ --data '{ "project_id": "project-123", @@ -876,7 +876,7 @@ async def delete_project( Example: ```bash curl --location --request DELETE 'http://0.0.0.0:4000/project/delete' \\ - --header 'Authorization: Bearer sk-1234' \\ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \\ --header 'Content-Type: application/json' \\ --data '{ "project_ids": ["project-123", "project-456"] @@ -983,7 +983,7 @@ async def project_info( Example: ```bash curl --location 'http://0.0.0.0:4000/project/info?project_id=project-123' \\ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import prisma_client @@ -1052,7 +1052,7 @@ async def list_projects( Example: ```bash curl --location 'http://0.0.0.0:4000/project/list' \\ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import prisma_client diff --git a/litellm-rust/crates/gateway-auth/tests/auth.rs b/litellm-rust/crates/gateway-auth/tests/auth.rs index a12230e8d5c..5a2a3ded834 100644 --- a/litellm-rust/crates/gateway-auth/tests/auth.rs +++ b/litellm-rust/crates/gateway-auth/tests/auth.rs @@ -94,8 +94,8 @@ async fn enforces_configured_keys_without_exposing_secrets( #[rstest] fn hash_token_matches_python_sha256_hexdigest() { assert_eq!( - hash_token("sk-1234"), - "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b" + hash_token("sk-9876"), + "595b23af2e99cee580245f388d3244a39247a25a3846e898e9c78841f8471a3e" ); } diff --git a/litellm/litellm_core_utils/logging_callback_manager.py b/litellm/litellm_core_utils/logging_callback_manager.py index 31523c9309d..075dc83146f 100644 --- a/litellm/litellm_core_utils/logging_callback_manager.py +++ b/litellm/litellm_core_utils/logging_callback_manager.py @@ -175,7 +175,7 @@ class LoggingCallbackManager: callback_type: generic_api endpoint: https://webhook-test.com/30343bc33591bc5e6dc44217ceae3e0a headers: - Authorization: Bearer sk-1234 + Authorization: Bearer $LITELLM_MASTER_KEY """ callback_config: Final = litellm.callback_settings.get(callback) diff --git a/litellm/litellm_core_utils/sensitive_data_masker.py b/litellm/litellm_core_utils/sensitive_data_masker.py index 747ad9bf5c9..828fd09d3ad 100644 --- a/litellm/litellm_core_utils/sensitive_data_masker.py +++ b/litellm/litellm_core_utils/sensitive_data_masker.py @@ -292,7 +292,7 @@ def _redact_sequence(values: Sequence[object], depth: int) -> Sequence[object]: """ masker = SensitiveDataMasker() data = { - "api_key": "sk-1234567890abcdef", + "api_key": "sk-9876543210abcdef", "redis_password": "very_secret_pass", "port": 6379, "tags": ["East US 2", "production", "test"] diff --git a/litellm/proxy/_lazy_openapi_snapshot.json b/litellm/proxy/_lazy_openapi_snapshot.json index 03408043f8e..d864ec04a8d 100644 --- a/litellm/proxy/_lazy_openapi_snapshot.json +++ b/litellm/proxy/_lazy_openapi_snapshot.json @@ -1241,7 +1241,7 @@ "paths": { "/access_group/list": { "get": { - "description": "List all access groups.\n\nReturns a list of all access groups with their model names, deployment counts, shared budget\nand the spend drawn against it.\n\nExample:\n```bash\ncurl -X GET 'http://localhost:4000/access_group/list' \\\n -H 'Authorization: Bearer sk-1234'\n```\n\nReturns:\n- ListAccessGroupsResponse with all access groups", + "description": "List all access groups.\n\nReturns a list of all access groups with their model names, deployment counts, shared budget\nand the spend drawn against it.\n\nExample:\n```bash\ncurl -X GET 'http://localhost:4000/access_group/list' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```\n\nReturns:\n- ListAccessGroupsResponse with all access groups", "operationId": "list_access_groups_access_group_list_get", "responses": { "200": { @@ -1268,7 +1268,7 @@ }, "/access_group/new": { "post": { - "description": "Create a new access group containing multiple model names.\n\nAn access group is a named collection of model groups that can be referenced\nby teams/keys for simplified access control.\n\nExample:\n```bash\ncurl -X POST 'http://localhost:4000/access_group/new' \\\n -H 'Authorization: Bearer sk-1234' \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"access_group\": \"production-models\",\n \"model_names\": [\"gpt-4\", \"claude-3-opus\", \"gemini-pro\"]\n }'\n```\n\nParameters:\n- access_group: str - The access group name (e.g., \"production-models\")\n- model_names: List[str] - List of existing model groups to include\n\nReturns:\n- NewModelGroupResponse with the created access group details\n\nRaises:\n- HTTPException 400: If any model names don't exist\n- HTTPException 500: If database operations fail", + "description": "Create a new access group containing multiple model names.\n\nAn access group is a named collection of model groups that can be referenced\nby teams/keys for simplified access control.\n\nExample:\n```bash\ncurl -X POST 'http://localhost:4000/access_group/new' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"access_group\": \"production-models\",\n \"model_names\": [\"gpt-4\", \"claude-3-opus\", \"gemini-pro\"]\n }'\n```\n\nParameters:\n- access_group: str - The access group name (e.g., \"production-models\")\n- model_names: List[str] - List of existing model groups to include\n\nReturns:\n- NewModelGroupResponse with the created access group details\n\nRaises:\n- HTTPException 400: If any model names don't exist\n- HTTPException 500: If database operations fail", "operationId": "create_model_group_access_group_new_post", "requestBody": { "content": { @@ -1315,7 +1315,7 @@ }, "/access_group/{access_group}/budget": { "delete": { - "description": "Clear the shared budget of an access group, leaving the group itself in place.\n\nExample:\n```bash\ncurl -X DELETE 'http://localhost:4000/access_group/production-models/budget' \\\n -H 'Authorization: Bearer sk-1234'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- DeleteAccessGroupBudgetResponse; budget_deleted is false when there was nothing to clear\n\nRaises:\n- HTTPException 404: If access group not found", + "description": "Clear the shared budget of an access group, leaving the group itself in place.\n\nExample:\n```bash\ncurl -X DELETE 'http://localhost:4000/access_group/production-models/budget' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- DeleteAccessGroupBudgetResponse; budget_deleted is false when there was nothing to clear\n\nRaises:\n- HTTPException 404: If access group not found", "operationId": "delete_access_group_budget_access_group__access_group__budget_delete", "parameters": [ { @@ -1361,7 +1361,7 @@ ] }, "get": { - "description": "Get the shared budget of an access group, and the spend drawn against it.\n\nExample:\n```bash\ncurl -X GET 'http://localhost:4000/access_group/production-models/budget' \\\n -H 'Authorization: Bearer sk-1234'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- AccessGroupBudgetResponse; budget is null when the group has no budget set\n\nRaises:\n- HTTPException 404: If access group not found", + "description": "Get the shared budget of an access group, and the spend drawn against it.\n\nExample:\n```bash\ncurl -X GET 'http://localhost:4000/access_group/production-models/budget' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- AccessGroupBudgetResponse; budget is null when the group has no budget set\n\nRaises:\n- HTTPException 404: If access group not found", "operationId": "get_access_group_budget_access_group__access_group__budget_get", "parameters": [ { @@ -1407,7 +1407,7 @@ ] }, "put": { - "description": "Set or replace the shared budget of an access group. Idempotent.\n\nEvery key that can reach a model in the group draws from this one budget.\n\nExample:\n```bash\ncurl -X PUT 'http://localhost:4000/access_group/production-models/budget' \\\n -H 'Authorization: Bearer sk-1234' \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"max_budget\": 100.0,\n \"budget_duration\": \"30d\"\n }'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n- max_budget: Optional[float] - Requests fail once the group's shared spend exceeds this\n- soft_budget: Optional[float] - Fires an alert when reached; requests still succeed\n- budget_duration: Optional[str] - Frequency of resetting the group's spend (e.g. '30d')\n- budget_id: Optional[str] - Link an existing budget instead of creating one\n\nReturns:\n- AccessGroupBudgetResponse with the stored budget and current spend\n\nRaises:\n- HTTPException 400: If no budget field is given, or budget_duration cannot be parsed\n- HTTPException 404: If access group not found", + "description": "Set or replace the shared budget of an access group. Idempotent.\n\nEvery key that can reach a model in the group draws from this one budget.\n\nExample:\n```bash\ncurl -X PUT 'http://localhost:4000/access_group/production-models/budget' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"max_budget\": 100.0,\n \"budget_duration\": \"30d\"\n }'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n- max_budget: Optional[float] - Requests fail once the group's shared spend exceeds this\n- soft_budget: Optional[float] - Fires an alert when reached; requests still succeed\n- budget_duration: Optional[str] - Frequency of resetting the group's spend (e.g. '30d')\n- budget_id: Optional[str] - Link an existing budget instead of creating one\n\nReturns:\n- AccessGroupBudgetResponse with the stored budget and current spend\n\nRaises:\n- HTTPException 400: If no budget field is given, or budget_duration cannot be parsed\n- HTTPException 404: If access group not found", "operationId": "set_access_group_budget_access_group__access_group__budget_put", "parameters": [ { @@ -1465,7 +1465,7 @@ }, "/access_group/{access_group}/delete": { "delete": { - "description": "Delete an access group.\n\nRemoves the access group from all deployments that have it.\n\nExample:\n```bash\ncurl -X DELETE 'http://localhost:4000/access_group/production-models/delete' \\\n -H 'Authorization: Bearer sk-1234'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- DeleteModelGroupResponse with deletion details\n\nRaises:\n- HTTPException 404: If access group not found", + "description": "Delete an access group.\n\nRemoves the access group from all deployments that have it.\n\nExample:\n```bash\ncurl -X DELETE 'http://localhost:4000/access_group/production-models/delete' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- DeleteModelGroupResponse with deletion details\n\nRaises:\n- HTTPException 404: If access group not found", "operationId": "delete_access_group_access_group__access_group__delete_delete", "parameters": [ { @@ -1513,7 +1513,7 @@ }, "/access_group/{access_group}/info": { "get": { - "description": "Get information about a specific access group.\n\nExample:\n```bash\ncurl -X GET 'http://localhost:4000/access_group/production-models/info' \\\n -H 'Authorization: Bearer sk-1234'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- AccessGroupInfo with the access group details, its shared budget and its spend\n\nRaises:\n- HTTPException 404: If access group not found", + "description": "Get information about a specific access group.\n\nExample:\n```bash\ncurl -X GET 'http://localhost:4000/access_group/production-models/info' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n\nReturns:\n- AccessGroupInfo with the access group details, its shared budget and its spend\n\nRaises:\n- HTTPException 404: If access group not found", "operationId": "get_access_group_info_access_group__access_group__info_get", "parameters": [ { @@ -1561,7 +1561,7 @@ }, "/access_group/{access_group}/update": { "put": { - "description": "Update an access group's model names.\n\nThis will:\n1. Remove the access group from all current deployments\n2. Add the access group to all deployments for the new model_names list\n\nExample:\n```bash\ncurl -X PUT 'http://localhost:4000/access_group/production-models/update' \\\n -H 'Authorization: Bearer sk-1234' \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"model_names\": [\"gpt-4\", \"claude-3-sonnet\"]\n }'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n- model_names: List[str] - New list of model groups to include\n\nReturns:\n- NewModelGroupResponse with the updated access group details\n\nRaises:\n- HTTPException 400: If any model names don't exist\n- HTTPException 404: If access group not found", + "description": "Update an access group's model names.\n\nThis will:\n1. Remove the access group from all current deployments\n2. Add the access group to all deployments for the new model_names list\n\nExample:\n```bash\ncurl -X PUT 'http://localhost:4000/access_group/production-models/update' \\\n -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"model_names\": [\"gpt-4\", \"claude-3-sonnet\"]\n }'\n```\n\nParameters:\n- access_group: str - The access group name (URL path parameter)\n- model_names: List[str] - New list of model groups to include\n\nReturns:\n- NewModelGroupResponse with the updated access group details\n\nRaises:\n- HTTPException 400: If any model names don't exist\n- HTTPException 404: If access group not found", "operationId": "update_access_group_access_group__access_group__update_put", "parameters": [ { @@ -26692,7 +26692,7 @@ }, "/cursor/chat/completions": { "post": { - "description": "Cursor BYOK endpoint. Accepts both request shapes Cursor sends to its OpenAI-compatible\nbase URL and always answers in chat completions format.\n\nCursor agent mode sends Responses API format bodies (`input`, flat tool defs, `reasoning`,\ncustom tools) to the chat/completions path while expecting chat completions responses;\nthose are routed through the Responses API pipeline and converted back. Genuine chat\ncompletions bodies (`messages` present) are routed through the standard chat completions\npipeline, after normalizing each level of the `tools` array and `tool_choice` to the chat\ncompletions shapes OpenAI requires. Cursor mixes Responses API shapes into chat bodies\nper level, independently: a flat tool def (`{\"type\": \"custom\", \"name\": \"ApplyPatch\", ...}`)\ngets nested under `custom`, and a flat grammar format\n(`{\"type\": \"grammar\", \"definition\", \"syntax\"}`) gets wrapped as\n`{\"type\": \"grammar\", \"grammar\": {...}}` wherever it appears, including inside tool defs\nCursor already sent pre-nested.\n\n```bash\ncurl -X POST http://localhost:4000/cursor/chat/completions -H \"Content-Type: application/json\" -H \"Authorization: Bearer sk-1234\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": [{\"role\": \"user\", \"content\": \"Hello\"}]\n}'\nResponds back in chat completions format.\n```", + "description": "Cursor BYOK endpoint. Accepts both request shapes Cursor sends to its OpenAI-compatible\nbase URL and always answers in chat completions format.\n\nCursor agent mode sends Responses API format bodies (`input`, flat tool defs, `reasoning`,\ncustom tools) to the chat/completions path while expecting chat completions responses;\nthose are routed through the Responses API pipeline and converted back. Genuine chat\ncompletions bodies (`messages` present) are routed through the standard chat completions\npipeline, after normalizing each level of the `tools` array and `tool_choice` to the chat\ncompletions shapes OpenAI requires. Cursor mixes Responses API shapes into chat bodies\nper level, independently: a flat tool def (`{\"type\": \"custom\", \"name\": \"ApplyPatch\", ...}`)\ngets nested under `custom`, and a flat grammar format\n(`{\"type\": \"grammar\", \"definition\", \"syntax\"}`) gets wrapped as\n`{\"type\": \"grammar\", \"grammar\": {...}}` wherever it appears, including inside tool defs\nCursor already sent pre-nested.\n\n```bash\ncurl -X POST http://localhost:4000/cursor/chat/completions -H \"Content-Type: application/json\" -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": [{\"role\": \"user\", \"content\": \"Hello\"}]\n}'\nResponds back in chat completions format.\n```", "operationId": "cursor_chat_completions_cursor_chat_completions_post", "responses": { "200": { @@ -28532,7 +28532,7 @@ }, "/openai/deployments/{model}/chat/completions": { "post": { - "description": "Follows the exact same API spec as `OpenAI's Chat API https://platform.openai.com/docs/api-reference/chat`\n\n```bash\ncurl -X POST http://localhost:4000/v1/chat/completions \n-H \"Content-Type: application/json\" \n-H \"Authorization: Bearer sk-1234\" \n-d '{\n \"model\": \"gpt-4o\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hello!\"\n }\n ]\n}'\n```", + "description": "Follows the exact same API spec as `OpenAI's Chat API https://platform.openai.com/docs/api-reference/chat`\n\n```bash\ncurl -X POST http://localhost:4000/v1/chat/completions \n-H \"Content-Type: application/json\" \n-H \"Authorization: Bearer $LITELLM_MASTER_KEY\" \n-d '{\n \"model\": \"gpt-4o\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hello!\"\n }\n ]\n}'\n```", "operationId": "chat_completion_openai_deployments__model__chat_completions_post", "parameters": [ { @@ -28665,7 +28665,7 @@ }, "/openai/deployments/{model}/completions": { "post": { - "description": "Follows the exact same API spec as `OpenAI's Completions API https://platform.openai.com/docs/api-reference/completions`\n\n```bash\ncurl -X POST http://localhost:4000/v1/completions \n-H \"Content-Type: application/json\" \n-H \"Authorization: Bearer sk-1234\" \n-d '{\n \"model\": \"gpt-3.5-turbo-instruct\",\n \"prompt\": \"Once upon a time\",\n \"max_tokens\": 50,\n \"temperature\": 0.7\n}'\n```", + "description": "Follows the exact same API spec as `OpenAI's Completions API https://platform.openai.com/docs/api-reference/completions`\n\n```bash\ncurl -X POST http://localhost:4000/v1/completions \n-H \"Content-Type: application/json\" \n-H \"Authorization: Bearer $LITELLM_MASTER_KEY\" \n-d '{\n \"model\": \"gpt-3.5-turbo-instruct\",\n \"prompt\": \"Once upon a time\",\n \"max_tokens\": 50,\n \"temperature\": 0.7\n}'\n```", "operationId": "completion_openai_deployments__model__completions_post", "parameters": [ { @@ -28718,7 +28718,7 @@ }, "/openai/deployments/{model}/embeddings": { "post": { - "description": "Follows the exact same API spec as `OpenAI's Embeddings API https://platform.openai.com/docs/api-reference/embeddings`\n\n```bash\ncurl -X POST http://localhost:4000/v1/embeddings \n-H \"Content-Type: application/json\" \n-H \"Authorization: Bearer sk-1234\" \n-d '{\n \"model\": \"text-embedding-ada-002\",\n \"input\": \"The quick brown fox jumps over the lazy dog\"\n}'\n```", + "description": "Follows the exact same API spec as `OpenAI's Embeddings API https://platform.openai.com/docs/api-reference/embeddings`\n\n```bash\ncurl -X POST http://localhost:4000/v1/embeddings \n-H \"Content-Type: application/json\" \n-H \"Authorization: Bearer $LITELLM_MASTER_KEY\" \n-d '{\n \"model\": \"text-embedding-ada-002\",\n \"input\": \"The quick brown fox jumps over the lazy dog\"\n}'\n```", "operationId": "embeddings_openai_deployments__model__embeddings_post", "parameters": [ { @@ -28771,7 +28771,7 @@ }, "/openai/deployments/{model}/images/edits": { "post": { - "description": "Follows the OpenAI Images API spec: https://platform.openai.com/docs/api-reference/images/create\n\n```bash\ncurl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST \"http://localhost:4000/v1/images/edits\" -H \"Authorization: Bearer sk-1234\" -F \"model=gpt-image-1\" -F \"image[]=@soap.png\" -F 'prompt=Create a studio ghibli image of this'\n```", + "description": "Follows the OpenAI Images API spec: https://platform.openai.com/docs/api-reference/images/create\n\n```bash\ncurl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST \"http://localhost:4000/v1/images/edits\" -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" -F \"model=gpt-image-1\" -F \"image[]=@soap.png\" -F 'prompt=Create a studio ghibli image of this'\n```", "operationId": "image_edit_api_openai_deployments__model__images_edits_post", "parameters": [ { @@ -28957,7 +28957,7 @@ }, "/openai/v1/responses": { "post": { - "description": "Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses\n\nSupports background mode with polling_via_cache for partial response retrieval.\nWhen background=true and polling_via_cache is enabled, returns a polling_id immediately\nand streams the response in the background, updating Redis cache.\n\n```bash\n# Normal request\ncurl -X POST http://localhost:4000/v1/responses -H \"Content-Type: application/json\" -H \"Authorization: Bearer sk-1234\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": \"Tell me about AI\"\n}'\n\n# Background request with polling\ncurl -X POST http://localhost:4000/v1/responses -H \"Content-Type: application/json\" -H \"Authorization: Bearer sk-1234\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": \"Tell me about AI\",\n \"background\": true\n}'\n```", + "description": "Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses\n\nSupports background mode with polling_via_cache for partial response retrieval.\nWhen background=true and polling_via_cache is enabled, returns a polling_id immediately\nand streams the response in the background, updating Redis cache.\n\n```bash\n# Normal request\ncurl -X POST http://localhost:4000/v1/responses -H \"Content-Type: application/json\" -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": \"Tell me about AI\"\n}'\n\n# Background request with polling\ncurl -X POST http://localhost:4000/v1/responses -H \"Content-Type: application/json\" -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": \"Tell me about AI\",\n \"background\": true\n}'\n```", "operationId": "responses_api_openai_v1_responses_post", "responses": { "200": { @@ -28990,7 +28990,7 @@ }, "/openai/v1/responses/compact": { "post": { - "description": "Compact a response by running a compaction pass over a conversation.\n\nReturns encrypted, opaque items that can be used to reduce context size.\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/compact\n\n```bash\ncurl -X POST http://localhost:4000/v1/responses/compact -H \"Content-Type: application/json\" -H \"Authorization: Bearer sk-1234\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": [{\"role\": \"user\", \"content\": \"Hello\"}]\n}'\n```", + "description": "Compact a response by running a compaction pass over a conversation.\n\nReturns encrypted, opaque items that can be used to reduce context size.\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/compact\n\n```bash\ncurl -X POST http://localhost:4000/v1/responses/compact -H \"Content-Type: application/json\" -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": [{\"role\": \"user\", \"content\": \"Hello\"}]\n}'\n```", "operationId": "compact_response_openai_v1_responses_compact_post", "responses": { "200": { @@ -29015,7 +29015,7 @@ }, "/openai/v1/responses/input_tokens": { "post": { - "description": "Count the input tokens of a Responses API request without calling the model.\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/input-tokens\n\n```bash\ncurl -X POST http://localhost:4000/v1/responses/input_tokens -H \"Content-Type: application/json\" -H \"Authorization: Bearer sk-1234\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": \"Hello, how are you?\"\n}'\n```\n\nReturns: `{\"object\": \"response.input_tokens\", \"input_tokens\": }`", + "description": "Count the input tokens of a Responses API request without calling the model.\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/input-tokens\n\n```bash\ncurl -X POST http://localhost:4000/v1/responses/input_tokens -H \"Content-Type: application/json\" -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" -d '{\n \"model\": \"gpt-4o\",\n \"input\": \"Hello, how are you?\"\n}'\n```\n\nReturns: `{\"object\": \"response.input_tokens\", \"input_tokens\": }`", "operationId": "responses_input_tokens_openai_v1_responses_input_tokens_post", "responses": { "200": { @@ -29040,7 +29040,7 @@ }, "/openai/v1/responses/{response_id}": { "delete": { - "description": "Delete a response by ID.\n\nSupports both:\n- Polling IDs (litellm_poll_*): Deletes from Redis cache\n- Provider response IDs: Passes through to provider API\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/delete\n\n```bash\ncurl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H \"Authorization: Bearer sk-1234\"\n```", + "description": "Delete a response by ID.\n\nSupports both:\n- Polling IDs (litellm_poll_*): Deletes from Redis cache\n- Provider response IDs: Passes through to provider API\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/delete\n\n```bash\ncurl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```", "operationId": "delete_response_openai_v1_responses__response_id__delete", "parameters": [ { @@ -29086,7 +29086,7 @@ ] }, "get": { - "description": "Get a response by ID.\n\nSupports both:\n- Polling IDs (litellm_poll_*): Returns cumulative cached content from background responses\n- Provider response IDs: Passes through to provider API\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/get\n\n```bash\n# Get polling response\ncurl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H \"Authorization: Bearer sk-1234\"\n\n# Get provider response\ncurl -X GET http://localhost:4000/v1/responses/resp_abc123 -H \"Authorization: Bearer sk-1234\"\n```", + "description": "Get a response by ID.\n\nSupports both:\n- Polling IDs (litellm_poll_*): Returns cumulative cached content from background responses\n- Provider response IDs: Passes through to provider API\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/get\n\n```bash\n# Get polling response\ncurl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n\n# Get provider response\ncurl -X GET http://localhost:4000/v1/responses/resp_abc123 -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```", "operationId": "get_response_openai_v1_responses__response_id__get", "parameters": [ { @@ -29134,7 +29134,7 @@ }, "/openai/v1/responses/{response_id}/cancel": { "post": { - "description": "Cancel a response by ID.\n\nSupports both:\n- Polling IDs (litellm_poll_*): Cancels background response and updates status in Redis\n- Provider response IDs: Passes through to provider API\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/cancel\n\n```bash\n# Cancel polling response\ncurl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H \"Authorization: Bearer sk-1234\"\n\n# Cancel provider response\ncurl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H \"Authorization: Bearer sk-1234\"\n```", + "description": "Cancel a response by ID.\n\nSupports both:\n- Polling IDs (litellm_poll_*): Cancels background response and updates status in Redis\n- Provider response IDs: Passes through to provider API\n\nFollows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/cancel\n\n```bash\n# Cancel polling response\ncurl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n\n# Cancel provider response\ncurl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```", "operationId": "cancel_response_openai_v1_responses__response_id__cancel_post", "parameters": [ { @@ -56443,7 +56443,7 @@ "paths": { "/v1/indexes": { "get": { - "description": "List all vector store indexes. Proxy admin only.\n\n```bash\ncurl -L -X GET 'http://0.0.0.0:4000/v1/indexes' -H 'Authorization: Bearer sk-1234'\n```", + "description": "List all vector store indexes. Proxy admin only.\n\n```bash\ncurl -L -X GET 'http://0.0.0.0:4000/v1/indexes' -H \"Authorization: Bearer $LITELLM_MASTER_KEY\"\n```", "operationId": "index_list_v1_indexes_get", "responses": { "200": { @@ -56468,7 +56468,7 @@ ] }, "post": { - "description": "Create an index. Just writes the index to the database.\n\n```bash\ncurl -L -X POST 'http://0.0.0.0:4000/v1/indexes' -H 'Content-Type: application/json' -H 'Authorization: Bearer sk-1234' -d '{\n \"index_name\": \"dall-e-3\",\n \"litellm_params\": {\n \"vector_store_index\": \"real-index-name\",\n \"vector_store_name\": \"azure-ai-search\"\n }\n }'\n```", + "description": "Create an index. Just writes the index to the database.\n\n```bash\ncurl -L -X POST 'http://0.0.0.0:4000/v1/indexes' -H 'Content-Type: application/json' -H \"Authorization: Bearer $LITELLM_MASTER_KEY\" -d '{\n \"index_name\": \"dall-e-3\",\n \"litellm_params\": {\n \"vector_store_index\": \"real-index-name\",\n \"vector_store_name\": \"azure-ai-search\"\n }\n }'\n```", "operationId": "index_create_v1_indexes_post", "requestBody": { "content": { diff --git a/litellm/proxy/auth/auth_utils.py b/litellm/proxy/auth/auth_utils.py index 829e792cf38..e49fa6e9acd 100644 --- a/litellm/proxy/auth/auth_utils.py +++ b/litellm/proxy/auth/auth_utils.py @@ -731,7 +731,7 @@ def route_in_additonal_public_routes(current_route: str): ```yaml general_settings: - master_key: sk-1234 + master_key: os.environ/LITELLM_MASTER_KEY public_routes: ["LiteLLMRoutes.public_routes", "/spend/calculate", "/api/*"] ``` """ diff --git a/litellm/proxy/auth/master_key_boot_check.py b/litellm/proxy/auth/master_key_boot_check.py index aa50c4e34c1..8fdb3f890a5 100644 --- a/litellm/proxy/auth/master_key_boot_check.py +++ b/litellm/proxy/auth/master_key_boot_check.py @@ -1,4 +1,5 @@ import atexit +import hashlib import sys from collections.abc import Awaitable, Callable, Mapping from dataclasses import dataclass, replace @@ -16,7 +17,9 @@ MASTER_KEY_SETTING: Final = "master_key" MASTER_KEY_ENV_VAR: Final = "LITELLM_MASTER_KEY" SALT_KEY_ENV_VAR: Final = "LITELLM_SALT_KEY" MIGRATE_FROM_MASTER_KEY_ENV_VAR: Final = "LITELLM_MIGRATE_FROM_MASTER_KEY" -PUBLICLY_KNOWN_MASTER_KEYS: Final = frozenset({"sk-1234"}) +PUBLICLY_KNOWN_MASTER_KEY_SHA256_DIGESTS: Final = frozenset( + {"88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b"} +) ROTATION_DOCS_URL: Final = "https://docs.litellm.ai/docs/proxy/master_key_rotations#proxy-refuses-to-start" _NEW_MASTER_KEY: Final = "sk-$(openssl rand -hex 32)" GENERATE_MASTER_KEY_COMMAND: Final = f'echo "{MASTER_KEY_ENV_VAR}={_NEW_MASTER_KEY}" | tee -a .env' @@ -203,7 +206,7 @@ def _unsafe_reason(master_key: str | None) -> UnsafeMasterKeyReason | None: stripped: Final = master_key.strip() if not stripped: return UnsafeMasterKeyReason.EMPTY - if stripped in PUBLICLY_KNOWN_MASTER_KEYS: + if hashlib.sha256(stripped.encode()).hexdigest() in PUBLICLY_KNOWN_MASTER_KEY_SHA256_DIGESTS: return UnsafeMasterKeyReason.PUBLICLY_KNOWN return None diff --git a/litellm/proxy/auth/user_api_key_auth.py b/litellm/proxy/auth/user_api_key_auth.py index 87bba4ecedd..adb6b86321d 100644 --- a/litellm/proxy/auth/user_api_key_auth.py +++ b/litellm/proxy/auth/user_api_key_auth.py @@ -506,7 +506,7 @@ def _get_bearer_token_or_received_api_key(api_key: str) -> str: api_key = api_key.replace("bearer ", "") elif api_key.startswith("AWS4-HMAC-SHA256"): # Handle AWS Signature V4 format from LangChain - # Format: AWS4-HMAC-SHA256 Credential=Bearer sk-12345/date/region/service/aws4_request, SignedHeaders=..., Signature=... + # Format: AWS4-HMAC-SHA256 Credential=Bearer $LITELLM_MASTER_KEY/date/region/service/aws4_request, SignedHeaders=..., Signature=... # Extract the Bearer token from the Credential field match = re.search(r"Credential=Bearer\s+([^/\s,]+)", api_key) if match: @@ -602,7 +602,7 @@ def _get_bearer_token( api_key = api_key.replace("bearer ", "") elif api_key.startswith("AWS4-HMAC-SHA256"): # Handle AWS Signature V4 format from LangChain - # Format: AWS4-HMAC-SHA256 Credential=Bearer sk-12345/date/region/service/aws4_request, SignedHeaders=..., Signature=... + # Format: AWS4-HMAC-SHA256 Credential=Bearer $LITELLM_MASTER_KEY/date/region/service/aws4_request, SignedHeaders=..., Signature=... # Extract the Bearer token from the Credential field match = re.search(r"Credential=Bearer\s+([^/\s,]+)", api_key) if match: @@ -1572,7 +1572,6 @@ async def _user_api_key_auth_builder( route=route, request=request, ) - # if user wants to pass LiteLLM_Master_Key as a custom header, example pass litellm keys as X-LiteLLM-Key: Bearer sk-1234 custom_litellm_key_header_name: Final = general_settings.get("litellm_key_header_name") if custom_litellm_key_header_name is not None: api_key = get_api_key_from_custom_header( diff --git a/litellm/proxy/batches_endpoints/endpoints.py b/litellm/proxy/batches_endpoints/endpoints.py index 1a5386b20d0..17565a420d9 100644 --- a/litellm/proxy/batches_endpoints/endpoints.py +++ b/litellm/proxy/batches_endpoints/endpoints.py @@ -244,7 +244,7 @@ async def create_batch( Example Curl ``` curl http://localhost:4000/v1/batches \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "input_file_id": "file-abc123", @@ -554,7 +554,7 @@ async def retrieve_batch( Example Curl ``` curl http://localhost:4000/v1/batches/batch_abc123 \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ ``` @@ -861,7 +861,7 @@ async def list_batches( Example Curl ``` curl http://localhost:4000/v1/batches?limit=2 \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ ``` @@ -1045,7 +1045,7 @@ async def cancel_batch( Example Curl ``` curl http://localhost:4000/v1/batches/batch_abc123/cancel \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -X POST diff --git a/litellm/proxy/caching_routes.py b/litellm/proxy/caching_routes.py index eccbf75667d..c621ec6a33a 100644 --- a/litellm/proxy/caching_routes.py +++ b/litellm/proxy/caching_routes.py @@ -133,7 +133,7 @@ async def cache_delete(request: Request): ```shell curl -X POST "http://0.0.0.0:4000/cache/delete" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{"keys": ["key1", "key2"]}' ``` @@ -226,7 +226,7 @@ async def cache_flushall(): Usage: ``` - curl -X POST http://0.0.0.0:4000/cache/flushall -H "Authorization: Bearer sk-1234" + curl -X POST http://0.0.0.0:4000/cache/flushall -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ try: diff --git a/litellm/proxy/common_utils/debug_utils.py b/litellm/proxy/common_utils/debug_utils.py index 2544321a1b6..5b77761d6dc 100644 --- a/litellm/proxy/common_utils/debug_utils.py +++ b/litellm/proxy/common_utils/debug_utils.py @@ -331,7 +331,7 @@ async def get_memory_summary( - garbage_collector: GC status and pending object counts Example usage: - curl http://localhost:4000/debug/memory/summary -H "Authorization: Bearer sk-1234" + curl http://localhost:4000/debug/memory/summary -H "Authorization: Bearer $LITELLM_MASTER_KEY" For detailed analysis, call GET /debug/memory/details For cache management, use the cache management endpoints @@ -692,7 +692,7 @@ async def get_memory_details( - include_process_info: Include process-level memory info using psutil (default: true) Example usage: - curl "http://localhost:4000/debug/memory/details?top_n=30" -H "Authorization: Bearer sk-1234" + curl "http://localhost:4000/debug/memory/details?top_n=30" -H "Authorization: Bearer $LITELLM_MASTER_KEY" All memory sizes are reported in both bytes and MB. """ @@ -754,10 +754,10 @@ async def configure_gc_thresholds_endpoint( - generation_2: Number of gen-1 collections before gen-2 collection (default: 10) Example for more aggressive collection: - curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=500" -H "Authorization: Bearer sk-1234" + curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=500" -H "Authorization: Bearer $LITELLM_MASTER_KEY" Example for less aggressive collection: - curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=1000" -H "Authorization: Bearer sk-1234" + curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=1000" -H "Authorization: Bearer $LITELLM_MASTER_KEY" Monitor memory usage with GET /debug/memory/summary after changes. """ @@ -796,7 +796,7 @@ async def get_debug_report( Nothing from the operator's config values, request data, or errors Example usage: - curl http://localhost:4000/debug/report -H "Authorization: Bearer sk-1234" + curl http://localhost:4000/debug/report -H "Authorization: Bearer $LITELLM_MASTER_KEY" """ if not is_proxy_admin(user_api_key_dict): raise HTTPException(status_code=403, detail="Only proxy admins can read /debug/report") diff --git a/litellm/proxy/container_endpoints/endpoints.py b/litellm/proxy/container_endpoints/endpoints.py index c1407979f29..3142ea62b24 100644 --- a/litellm/proxy/container_endpoints/endpoints.py +++ b/litellm/proxy/container_endpoints/endpoints.py @@ -52,7 +52,7 @@ async def create_container( Example: ```bash curl -X POST "http://localhost:4000/v1/containers" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "My Container", @@ -66,7 +66,7 @@ async def create_container( Or specify provider via header: ```bash curl -X POST "http://localhost:4000/v1/containers" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "custom-llm-provider: azure" \ -H "Content-Type: application/json" \ -d '{ @@ -187,13 +187,13 @@ async def list_containers( Example: ```bash curl -X GET "http://localhost:4000/v1/containers?limit=20&order=desc" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Or specify provider via header or query param: ```bash curl -X GET "http://localhost:4000/v1/containers?custom_llm_provider=azure" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import ( @@ -290,13 +290,13 @@ async def retrieve_container( Example: ```bash curl -X GET "http://localhost:4000/v1/containers/cntr_123" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Or specify provider via header: ```bash curl -X GET "http://localhost:4000/v1/containers/cntr_123" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "custom-llm-provider: azure" ``` """ @@ -396,13 +396,13 @@ async def delete_container( Example: ```bash curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Or specify provider via header: ```bash curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "custom-llm-provider: azure" ``` """ diff --git a/litellm/proxy/fine_tuning_endpoints/endpoints.py b/litellm/proxy/fine_tuning_endpoints/endpoints.py index e09f1ec8ba8..e1fe7c21754 100644 --- a/litellm/proxy/fine_tuning_endpoints/endpoints.py +++ b/litellm/proxy/fine_tuning_endpoints/endpoints.py @@ -87,7 +87,7 @@ async def create_fine_tuning_job( ``` curl http://localhost:4000/v1/fine_tuning/jobs \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-3.5-turbo", "training_file": "file-abc123", diff --git a/litellm/proxy/google_endpoints/endpoints.py b/litellm/proxy/google_endpoints/endpoints.py index 9d39430cfa9..dd5dc66d82b 100644 --- a/litellm/proxy/google_endpoints/endpoints.py +++ b/litellm/proxy/google_endpoints/endpoints.py @@ -246,7 +246,7 @@ async def create_interaction( Example: ```bash curl -X POST "http://localhost:4000/v1beta/interactions" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gemini/gemini-2.5-flash", diff --git a/litellm/proxy/health_endpoints/_health_endpoints.py b/litellm/proxy/health_endpoints/_health_endpoints.py index 2a0b528a50b..4c077b02c00 100644 --- a/litellm/proxy/health_endpoints/_health_endpoints.py +++ b/litellm/proxy/health_endpoints/_health_endpoints.py @@ -298,7 +298,7 @@ async def health_services_endpoint( Example: ``` curl -L -X GET 'http://0.0.0.0:4000/health/services?service=datadog' \ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ try: @@ -2086,7 +2086,7 @@ async def test_model_connection( ```bash # If model is configured in proxy_config.yaml, you only need to specify the model name: curl -X POST 'http://localhost:4000/health/test_connection' \\ - -H 'Authorization: Bearer sk-1234' \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H 'Content-Type: application/json' \\ -d '{ "litellm_params": { @@ -2099,7 +2099,7 @@ async def test_model_connection( # You can also override specific params or test with custom credentials: curl -X POST 'http://localhost:4000/health/test_connection' \\ - -H 'Authorization: Bearer sk-1234' \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H 'Content-Type: application/json' \\ -d '{ "litellm_params": { diff --git a/litellm/proxy/hooks/key_management_event_hooks.py b/litellm/proxy/hooks/key_management_event_hooks.py index 5dc0f659a8d..a1100474671 100644 --- a/litellm/proxy/hooks/key_management_event_hooks.py +++ b/litellm/proxy/hooks/key_management_event_hooks.py @@ -292,7 +292,7 @@ class KeyManagementEventHooks: Args: secret_name: Name of the virtual key - secret_token: Value of the virtual key (example: sk-1234) + secret_token: Value of the virtual key (example: $LITELLM_API_KEY) """ if litellm._key_management_settings is not None: if litellm._key_management_settings.store_virtual_keys is True: @@ -330,7 +330,7 @@ class KeyManagementEventHooks: Args: current_secret_name: Current name of the virtual key new_secret_name: New name of the virtual key - new_secret_value: New value of the virtual key (example: sk-1234) + new_secret_value: New value of the virtual key (example: $LITELLM_API_KEY) team_id: Optional team ID to get team-specific secret manager settings """ secret_manager: Final = KeyManagementEventHooks._stored_virtual_key_secret_manager() diff --git a/litellm/proxy/hooks/model_max_budget_limiter.py b/litellm/proxy/hooks/model_max_budget_limiter.py index d019271d404..e810b98f336 100644 --- a/litellm/proxy/hooks/model_max_budget_limiter.py +++ b/litellm/proxy/hooks/model_max_budget_limiter.py @@ -294,7 +294,7 @@ class _PROXY_VirtualKeyModelMaxBudgetLimiter(RouterBudgetLimiting): """ Handles budgets for model + virtual key - Example: key=sk-1234567890, model=gpt-4o, max_budget=100, time_period=1d + Example: key=$LITELLM_API_KEY, model=gpt-4o, max_budget=100, time_period=1d """ def __init__(self, dual_cache: DualCache): @@ -497,7 +497,7 @@ class _PROXY_VirtualKeyModelMaxBudgetLimiter(RouterBudgetLimiting): """ Track spend for virtual key + model in DualCache - Example: key=sk-1234567890, model=gpt-4o, max_budget=100, time_period=1d + Example: key=$LITELLM_API_KEY, model=gpt-4o, max_budget=100, time_period=1d """ verbose_proxy_logger.debug("in RouterBudgetLimiting.async_log_success_event") standard_logging_payload: Final[StandardLoggingPayload | None] = kwargs.get("standard_logging_object", None) diff --git a/litellm/proxy/image_endpoints/endpoints.py b/litellm/proxy/image_endpoints/endpoints.py index 4dc147b6687..cd64363f3d3 100644 --- a/litellm/proxy/image_endpoints/endpoints.py +++ b/litellm/proxy/image_endpoints/endpoints.py @@ -259,7 +259,7 @@ async def image_edit_api( curl -s -D >(grep -i x-request-id >&2) \ -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) \ -X POST "http://localhost:4000/v1/images/edits" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -F "model=gpt-image-1" \ -F "image[]=@soap.png" \ -F 'prompt=Create a studio ghibli image of this' diff --git a/litellm/proxy/management_endpoints/customer_endpoints.py b/litellm/proxy/management_endpoints/customer_endpoints.py index 2e629185028..55352ede1dc 100644 --- a/litellm/proxy/management_endpoints/customer_endpoints.py +++ b/litellm/proxy/management_endpoints/customer_endpoints.py @@ -170,7 +170,7 @@ async def block_user(data: BlockUsers): ``` curl -X POST "http://0.0.0.0:8000/user/block" - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ "user_ids": [, ...] }' @@ -222,7 +222,7 @@ async def unblock_user(data: BlockUsers): Example ``` curl -X POST "http://0.0.0.0:8000/user/unblock" - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ "user_ids": [, ...] }' @@ -375,7 +375,7 @@ async def new_end_user( Example curl: ``` curl --location 'http://0.0.0.0:4000/customer/new' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "user_id" : "ishaan-jaff-3", @@ -387,7 +387,7 @@ async def new_end_user( # With object permissions curl -L -X POST 'http://localhost:4000/customer/new' \ - -H 'Authorization: Bearer sk-1234' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H 'Content-Type: application/json' \ -d '{ "user_id": "user_1", @@ -558,7 +558,7 @@ async def end_user_info( Example curl: ``` curl -X GET 'http://localhost:4000/customer/info?end_user_id=test-litellm-user-4' \ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ try: @@ -638,7 +638,7 @@ async def update_end_user( Example curl: ``` curl --location 'http://0.0.0.0:4000/customer/update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "user_id": "test-litellm-user-4", @@ -648,7 +648,7 @@ async def update_end_user( # Updating object permissions curl -L -X POST 'http://localhost:4000/customer/update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "user_id": "user_1", @@ -797,7 +797,7 @@ async def delete_end_user( Example curl: ``` curl --location 'http://0.0.0.0:4000/customer/delete' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "user_ids" :["ishaan-jaff-5"] @@ -872,7 +872,7 @@ async def list_end_user( Example curl: ``` curl --location --request GET 'http://0.0.0.0:4000/customer/list' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ diff --git a/litellm/proxy/management_endpoints/internal_user_endpoints.py b/litellm/proxy/management_endpoints/internal_user_endpoints.py index 5054ceb92d5..69efb9c209f 100644 --- a/litellm/proxy/management_endpoints/internal_user_endpoints.py +++ b/litellm/proxy/management_endpoints/internal_user_endpoints.py @@ -543,7 +543,7 @@ async def new_user( ```shell curl -X POST "http://localhost:4000/user/new" \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "username": "new_user", "email": "new_user@example.com" @@ -952,7 +952,7 @@ async def user_info( Example request ``` curl -X GET 'http://localhost:4000/user/info?user_id=krrish7%40berri.ai' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import model_max_budget_limiter, prisma_client @@ -1105,7 +1105,7 @@ async def user_info_v2( Example request: ``` curl -X GET 'http://localhost:4000/v2/user/info?user_id=user123' \\ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import model_max_budget_limiter, prisma_client @@ -1685,7 +1685,7 @@ async def user_update( ``` curl --location 'http://0.0.0.0:4000/user/update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "user_id": "test-litellm-user-4", @@ -1873,7 +1873,7 @@ async def bulk_user_update( Example request for specific users: ```bash curl --location 'http://0.0.0.0:4000/user/bulk_update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "users": [ @@ -1894,7 +1894,7 @@ async def bulk_user_update( Example request for all users: ```bash curl --location 'http://0.0.0.0:4000/user/bulk_update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "all_users": true, @@ -2415,7 +2415,7 @@ async def delete_user( ``` curl --location 'http://0.0.0.0:4000/user/delete' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ diff --git a/litellm/proxy/management_endpoints/key_management_endpoints.py b/litellm/proxy/management_endpoints/key_management_endpoints.py index 6dd9888d925..f2dc2995e32 100644 --- a/litellm/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/proxy/management_endpoints/key_management_endpoints.py @@ -2028,7 +2028,7 @@ async def generate_key_fn( ```bash curl --location 'http://0.0.0.0:4000/key/generate' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "permissions": {"allow_pii_controls": true} @@ -2226,7 +2226,7 @@ async def generate_service_account_key_fn( ```bash curl --location 'http://0.0.0.0:4000/key/generate' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "permissions": {"allow_pii_controls": true} @@ -3440,10 +3440,10 @@ async def update_key_fn( Example: ```bash curl --location 'http://0.0.0.0:4000/key/update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ - "key": "sk-1234", + "key": "sk-", "key_alias": "my-key", "user_id": "user-1234", "team_id": "team-1234", @@ -3666,12 +3666,12 @@ async def bulk_update_keys( Example request: ```bash curl --location 'http://0.0.0.0:4000/key/bulk_update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "keys": [ { - "key": "sk-1234", + "key": "sk-", "max_budget": 100.0, "team_id": "team-123", "tags": ["production", "api"] @@ -4097,7 +4097,7 @@ async def delete_key_fn( Example: ```bash curl --location 'http://0.0.0.0:4000/key/delete' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "keys": ["sk-QWrxEynunsNpV1zT48HIrw"] @@ -4276,7 +4276,7 @@ async def info_key_fn_v2( Example Curl: ``` curl -X GET "http://0.0.0.0:4000/key/info" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d {"keys": ["sk-1", "sk-2", "sk-3"]} ``` """ @@ -4405,7 +4405,7 @@ async def info_key_fn( Example Curl: ``` curl -X GET "http://0.0.0.0:4000/key/info?key=d5345c0ecc68ae6295c69f91926b2bd379e25481a40c34b5884d157a9f65d8fa" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example Curl - if no key is passed, it will use the Key Passed in Authorization Header @@ -5795,8 +5795,8 @@ async def regenerate_key_fn( Example: ```bash - curl --location --request POST 'http://localhost:4000/key/sk-1234/regenerate' \ - --header 'Authorization: Bearer sk-1234' \ + curl --location --request POST "http://localhost:4000/key/$LITELLM_API_KEY/regenerate" \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data-raw '{ "max_budget": 100, @@ -7329,7 +7329,7 @@ async def block_key( Example: ```bash curl --location 'http://0.0.0.0:4000/key/block' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "key": "sk-Fn8Ej39NxjAXrvpUGKghGw" @@ -7443,7 +7443,7 @@ async def unblock_key( Example: ```bash curl --location 'http://0.0.0.0:4000/key/unblock' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "key": "sk-Fn8Ej39NxjAXrvpUGKghGw" @@ -7560,7 +7560,7 @@ async def key_health( ```bash curl -X POST "http://localhost:4000/key/health" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" ``` diff --git a/litellm/proxy/management_endpoints/management_v1/budgets.py b/litellm/proxy/management_endpoints/management_v1/budgets.py index 1fe9c94ac5f..1970a0797ef 100644 --- a/litellm/proxy/management_endpoints/management_v1/budgets.py +++ b/litellm/proxy/management_endpoints/management_v1/budgets.py @@ -164,7 +164,7 @@ async def list_budgets( Example curl: ``` curl --location --globoff 'http://0.0.0.0:4000/management/v1/budgets?sort=-max_budget&filter[budget_duration][in]=7d,30d&page_size=25' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ try: diff --git a/litellm/proxy/management_endpoints/management_v1/spend_logs.py b/litellm/proxy/management_endpoints/management_v1/spend_logs.py index e9e6e05ce15..b122840004c 100644 --- a/litellm/proxy/management_endpoints/management_v1/spend_logs.py +++ b/litellm/proxy/management_endpoints/management_v1/spend_logs.py @@ -188,7 +188,7 @@ async def list_spend_log_end_users( Example curl: ``` curl --location --globoff 'http://0.0.0.0:4000/management/v1/spend_logs/end_users?filter[startTime][gte]=2026-07-23T00:00:00Z&filter[startTime][lte]=2026-07-24T00:00:00Z&page_size=50&q=acme' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ return await _list_spend_log_facet( diff --git a/litellm/proxy/management_endpoints/management_v1/teams.py b/litellm/proxy/management_endpoints/management_v1/teams.py index 215a82c950c..eab6449af8f 100644 --- a/litellm/proxy/management_endpoints/management_v1/teams.py +++ b/litellm/proxy/management_endpoints/management_v1/teams.py @@ -51,7 +51,7 @@ async def bulk_delete_team_members_action( Example curl: ``` curl --location 'http://0.0.0.0:4000/management/v1/teams/team-1/members/bulk_delete' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{"members": [{"user_id": "user-1"}, {"user_email": "user-2@example.com"}]}' ``` @@ -135,7 +135,7 @@ async def bulk_update_team_member_budgets_action( Example curl: ``` curl --location 'http://0.0.0.0:4000/management/v1/teams/team-1/members/bulk_update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{"members": [{"user_id": "user-1", "max_budget_in_team": 10}, {"user_email": "user-2@example.com", "max_budget_in_team": 10, "budget_duration": "30d"}]}' ``` diff --git a/litellm/proxy/management_endpoints/management_v1/users.py b/litellm/proxy/management_endpoints/management_v1/users.py index fdece34d3a2..920aad2d2e5 100644 --- a/litellm/proxy/management_endpoints/management_v1/users.py +++ b/litellm/proxy/management_endpoints/management_v1/users.py @@ -55,7 +55,7 @@ async def bulk_create_users_route( ``` curl -X POST "http://localhost:4000/management/v1/users/bulk" \\ -H "Content-Type: application/json" \\ - -H "Authorization: Bearer sk-1234" \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -d '{ "users": [ {"user_email": "a@example.com", "user_role": "internal_user", "teams": ["team-1"]}, @@ -136,7 +136,7 @@ async def bulk_delete_users_action( Example curl: ``` curl --location 'http://0.0.0.0:4000/management/v1/users/bulk_delete' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{"user_ids": ["user-1", "user-2"]}' ``` diff --git a/litellm/proxy/management_endpoints/model_access_group_management_endpoints.py b/litellm/proxy/management_endpoints/model_access_group_management_endpoints.py index e960bdfe337..af469376289 100644 --- a/litellm/proxy/management_endpoints/model_access_group_management_endpoints.py +++ b/litellm/proxy/management_endpoints/model_access_group_management_endpoints.py @@ -584,7 +584,7 @@ async def create_model_group( Example: ```bash curl -X POST 'http://localhost:4000/access_group/new' \\ - -H 'Authorization: Bearer sk-1234' \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H 'Content-Type: application/json' \\ -d '{ "access_group": "production-models", @@ -729,7 +729,7 @@ async def list_access_groups( Example: ```bash curl -X GET 'http://localhost:4000/access_group/list' \\ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Returns: @@ -777,7 +777,7 @@ async def get_access_group_info( Example: ```bash curl -X GET 'http://localhost:4000/access_group/production-models/info' \\ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Parameters: @@ -841,7 +841,7 @@ async def update_access_group( Example: ```bash curl -X PUT 'http://localhost:4000/access_group/production-models/update' \\ - -H 'Authorization: Bearer sk-1234' \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H 'Content-Type: application/json' \\ -d '{ "model_names": ["gpt-4", "claude-3-sonnet"] @@ -993,7 +993,7 @@ async def delete_access_group( Example: ```bash curl -X DELETE 'http://localhost:4000/access_group/production-models/delete' \\ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Parameters: @@ -1099,7 +1099,7 @@ async def get_access_group_budget( Example: ```bash curl -X GET 'http://localhost:4000/access_group/production-models/budget' \\ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Parameters: @@ -1139,7 +1139,7 @@ async def set_access_group_budget( Example: ```bash curl -X PUT 'http://localhost:4000/access_group/production-models/budget' \\ - -H 'Authorization: Bearer sk-1234' \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H 'Content-Type: application/json' \\ -d '{ "max_budget": 100.0, @@ -1213,7 +1213,7 @@ async def delete_access_group_budget( Example: ```bash curl -X DELETE 'http://localhost:4000/access_group/production-models/budget' \\ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Parameters: diff --git a/litellm/proxy/management_endpoints/organization_endpoints.py b/litellm/proxy/management_endpoints/organization_endpoints.py index 26abe35b49a..3c1b31b68ef 100644 --- a/litellm/proxy/management_endpoints/organization_endpoints.py +++ b/litellm/proxy/management_endpoints/organization_endpoints.py @@ -404,7 +404,7 @@ async def new_organization( ```bash curl --location 'http://0.0.0.0:4000/organization/new' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ @@ -422,7 +422,7 @@ async def new_organization( ```bash curl --location 'http://0.0.0.0:4000/organization/new' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ @@ -1111,13 +1111,13 @@ async def list_organization( Example: ``` curl --location --request GET 'http://0.0.0.0:4000/organization/list?org_alias=my-org' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example with org_id: ``` curl --location --request GET 'http://0.0.0.0:4000/organization/list?org_id=123e4567-e89b-12d3-a456-426614174000' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import prisma_client @@ -1311,7 +1311,7 @@ async def organization_member_add( Example: ``` curl -X POST 'http://0.0.0.0:4000/organization/member_add' \ - -H 'Authorization: Bearer sk-1234' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H 'Content-Type: application/json' \ -d '{ "organization_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849", diff --git a/litellm/proxy/management_endpoints/team_callback_endpoints.py b/litellm/proxy/management_endpoints/team_callback_endpoints.py index bc15d4a4434..a59342fa044 100644 --- a/litellm/proxy/management_endpoints/team_callback_endpoints.py +++ b/litellm/proxy/management_endpoints/team_callback_endpoints.py @@ -295,7 +295,7 @@ async def add_team_callbacks( ``` curl -X POST 'http:/localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback' \ -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer sk-1234' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "callback_name": "langfuse", "callback_type": "success", @@ -468,7 +468,7 @@ async def delete_team_callback( Example curl: ``` curl -X DELETE 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback/langsmith' \ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Covers callbacks registered through POST /team/{team_id}/callback and the Admin UI. Teams still @@ -604,7 +604,7 @@ async def disable_team_logging( Example curl: ``` curl -X POST 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/disable_logging' \ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` @@ -736,7 +736,7 @@ async def get_team_callbacks( Example curl: ``` curl -X GET 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback' \ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` This will return the callback settings for the team with id dbe2f686-a686-4896-864a-4c3924458709 diff --git a/litellm/proxy/management_endpoints/team_endpoints.py b/litellm/proxy/management_endpoints/team_endpoints.py index 20005862b1a..818c0590707 100644 --- a/litellm/proxy/management_endpoints/team_endpoints.py +++ b/litellm/proxy/management_endpoints/team_endpoints.py @@ -1407,7 +1407,7 @@ async def new_team( Example Request: ``` curl --location 'http://0.0.0.0:4000/team/new' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "team_alias": "my-new-team_2", @@ -1419,7 +1419,7 @@ async def new_team( ``` curl --location 'http://0.0.0.0:4000/team/new' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "team_alias": "QA Prod Bot", @@ -2167,7 +2167,7 @@ async def update_team( ``` curl --location 'http://0.0.0.0:4000/team/update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data-raw '{ "team_id": "8d916b1c-510d-4894-a334-1c16a93344f5", @@ -2178,7 +2178,7 @@ async def update_team( Example - Update Team `max_budget` budget ``` curl --location 'http://0.0.0.0:4000/team/update' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data-raw '{ "team_id": "8d916b1c-510d-4894-a334-1c16a93344f5", @@ -2597,7 +2597,7 @@ async def patch_team( ``` curl --location --request PATCH 'http://0.0.0.0:4000/team/8d916b1c-510d-4894-a334-1c16a93344f5' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data-raw '{ "metadata": {"cost_center": "1234", "deprecated_key": null} @@ -3368,7 +3368,7 @@ async def team_member_add( ``` curl -X POST 'http://0.0.0.0:4000/team/member_add' \ - -H 'Authorization: Bearer sk-1234' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H 'Content-Type: application/json' \ -d '{"team_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849", "member": {"role": "user", "user_id": "krrish247652@berri.ai"}}' @@ -3549,7 +3549,7 @@ async def team_member_delete( ``` curl -X POST 'http://0.0.0.0:8000/team/member_delete' \ - -H 'Authorization: Bearer sk-1234' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H 'Content-Type: application/json' \ @@ -4196,7 +4196,7 @@ async def bulk_team_member_add( Example request: ```bash curl --location 'http://0.0.0.0:4000/team/bulk_member_add' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "team_id": "team-1234", @@ -4329,7 +4329,7 @@ async def delete_team( ``` curl --location 'http://0.0.0.0:4000/team/delete' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data-raw '{ "team_ids": ["8d916b1c-510d-4894-a334-1c16a93344f5"] @@ -5141,7 +5141,7 @@ async def block_team( Example: ``` curl --location 'http://0.0.0.0:4000/team/block' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "team_id": "team-1234" @@ -5196,7 +5196,7 @@ async def unblock_team( Example: ``` curl --location 'http://0.0.0.0:4000/team/unblock' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "team_id": "team-1234" @@ -5867,7 +5867,7 @@ async def list_team( """ ``` curl --location --request GET 'http://0.0.0.0:4000/team/list' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Parameters: @@ -6071,7 +6071,7 @@ async def team_model_add( Example Request: ``` curl --location 'http://0.0.0.0:4000/team/model/add' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "team_id": "team-1234", @@ -6187,7 +6187,7 @@ async def team_model_delete( Example Request: ``` curl --location 'http://0.0.0.0:4000/team/model/delete' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --header 'Content-Type: application/json' \ --data '{ "team_id": "team-1234", diff --git a/litellm/proxy/ocr_endpoints/endpoints.py b/litellm/proxy/ocr_endpoints/endpoints.py index 01c4f806e94..81d9f8a7b43 100644 --- a/litellm/proxy/ocr_endpoints/endpoints.py +++ b/litellm/proxy/ocr_endpoints/endpoints.py @@ -272,7 +272,7 @@ async def ocr( **1. JSON body** (Mistral OCR API compatible): ```bash curl -X POST "http://localhost:4000/v1/ocr" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "mistral-ocr", @@ -286,7 +286,7 @@ async def ocr( **2. Multipart form file upload**: ```bash curl -X POST "http://localhost:4000/v1/ocr" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -F "model=mistral-ocr" \ -F "file=@document.pdf" ``` diff --git a/litellm/proxy/openai_files_endpoints/files_endpoints.py b/litellm/proxy/openai_files_endpoints/files_endpoints.py index e51d912dcfd..e170e1cf894 100644 --- a/litellm/proxy/openai_files_endpoints/files_endpoints.py +++ b/litellm/proxy/openai_files_endpoints/files_endpoints.py @@ -569,7 +569,7 @@ async def create_file( Example Curl ``` curl http://localhost:4000/v1/files \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -F purpose="batch" \ -F file="@mydata.jsonl" -F expires_after[anchor]="created_at" \ @@ -970,7 +970,7 @@ async def get_file_content( Example Curl ``` curl http://localhost:4000/v1/files/file-abc123/content \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ @@ -1282,7 +1282,7 @@ async def get_file( Example Curl ``` curl http://localhost:4000/v1/files/file-abc123 \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ @@ -1708,7 +1708,7 @@ async def list_files( Example Curl ``` curl http://localhost:4000/v1/files\ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 56a35c53a4a..d1147c48558 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -12065,7 +12065,7 @@ async def chat_completion( -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-4o", @@ -12229,7 +12229,7 @@ async def completion( -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-3.5-turbo-instruct", @@ -12413,7 +12413,7 @@ async def embeddings( -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "text-embedding-ada-002", @@ -12521,7 +12521,7 @@ async def moderations( ``` curl --location 'http://0.0.0.0:4000/moderations' \ --header 'Content-Type: application/json' \ - --header 'Authorization: Bearer sk-1234' \ + --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ --data '{"input": "Sample text goes here", "model": "text-moderation-stable"}' ``` """ @@ -14175,7 +14175,7 @@ async def supported_openai_params(model: str): Example curl: ``` curl -X GET --location 'http://localhost:4000/utils/supported_openai_params?model=gpt-3.5-turbo-16k' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.litellm_core_utils.get_llm_provider_logic import declared_authenticating_provider @@ -14220,7 +14220,7 @@ async def model_info_lookup(model: str, custom_llm_provider: str | None = None): Example curl: ``` curl -X GET --location 'http://localhost:4000/utils/model_info?model=gpt-4o&custom_llm_provider=openai' \ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ detail: Final = {"error": f"model={model}, custom_llm_provider={custom_llm_provider} is not in the model cost map"} @@ -15464,7 +15464,7 @@ async def model_info_v2( Example request: ``` curl -X GET 'http://localhost:4000/v2/model/info?include_team_models=true&page=1&size=50' \\ - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example response: @@ -16414,7 +16414,7 @@ async def model_deprecations( Example: ```shell curl -X GET 'http://localhost:4000/model/deprecations' \\ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ return collect_model_deprecations(llm_router=llm_router, warn_within_days=warn_within_days) @@ -16476,7 +16476,7 @@ async def model_group_info( curl -X 'GET' \ 'http://localhost:4000/model_group/info' \ -H 'accept: application/json' \ - -H 'x-api-key: sk-1234' + -H "x-api-key: $LITELLM_MASTER_KEY" ``` Example Request (Specific Model Group): @@ -16484,7 +16484,7 @@ async def model_group_info( curl -X 'GET' \ 'http://localhost:4000/model_group/info?model_group=rerank-english-v3.0' \ -H 'accept: application/json' \ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example Request (Specific Wildcard Model Group): (e.g. `model_name: openai/*` on config.yaml) @@ -16492,7 +16492,7 @@ async def model_group_info( curl -X 'GET' \ 'http://localhost:4000/model_group/info?model_group=openai/tts-1' -H 'accept: application/json' \ - -H 'Authorization: Bearersk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Learn how to use and set wildcard models [here](https://docs.litellm.ai/docs/wildcard_routing) diff --git a/litellm/proxy/rag_endpoints/endpoints.py b/litellm/proxy/rag_endpoints/endpoints.py index 936296cba26..0913d216678 100644 --- a/litellm/proxy/rag_endpoints/endpoints.py +++ b/litellm/proxy/rag_endpoints/endpoints.py @@ -550,7 +550,7 @@ async def rag_ingest( ## Form upload (for files): ```bash curl -X POST "http://localhost:4000/v1/rag/ingest" \\ - -H "Authorization: Bearer sk-1234" \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -F file="@document.pdf" \\ -F 'ingest_options={"vector_store": {"custom_llm_provider": "openai"}}' ``` @@ -558,7 +558,7 @@ async def rag_ingest( ## JSON body (for URLs): ```bash curl -X POST "http://localhost:4000/v1/rag/ingest" \\ - -H "Authorization: Bearer sk-1234" \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H "Content-Type: application/json" \\ -d '{ "file_url": "https://example.com/document.pdf", @@ -569,7 +569,7 @@ async def rag_ingest( ## Bedrock: ```bash curl -X POST "http://localhost:4000/v1/rag/ingest" \\ - -H "Authorization: Bearer sk-1234" \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -F file="@document.pdf" \\ -F 'ingest_options={"vector_store": {"custom_llm_provider": "bedrock"}}' ``` @@ -725,7 +725,7 @@ async def rag_query( ## Example Request: ```bash curl -X POST "http://localhost:4000/v1/rag/query" \\ - -H "Authorization: Bearer sk-1234" \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H "Content-Type: application/json" \\ -d '{ "model": "gpt-4o-mini", @@ -741,7 +741,7 @@ async def rag_query( ## With Reranking: ```bash curl -X POST "http://localhost:4000/v1/rag/query" \\ - -H "Authorization: Bearer sk-1234" \\ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \\ -H "Content-Type: application/json" \\ -d '{ "model": "gpt-4o-mini", diff --git a/litellm/proxy/response_api_endpoints/endpoints.py b/litellm/proxy/response_api_endpoints/endpoints.py index 20461cc9a01..df27696155d 100644 --- a/litellm/proxy/response_api_endpoints/endpoints.py +++ b/litellm/proxy/response_api_endpoints/endpoints.py @@ -226,7 +226,7 @@ async def responses_api( # Normal request curl -X POST http://localhost:4000/v1/responses \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-4o", "input": "Tell me about AI" @@ -235,7 +235,7 @@ async def responses_api( # Background request with polling curl -X POST http://localhost:4000/v1/responses \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-4o", "input": "Tell me about AI", @@ -518,7 +518,7 @@ async def cursor_chat_completions( ```bash curl -X POST http://localhost:4000/cursor/chat/completions \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-4o", "input": [{"role": "user", "content": "Hello"}] @@ -711,11 +711,11 @@ async def get_response( ```bash # Get polling response curl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" # Get provider response curl -X GET http://localhost:4000/v1/responses/resp_abc123 \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import ( @@ -826,7 +826,7 @@ async def delete_response( ```bash curl -X DELETE http://localhost:4000/v1/responses/resp_abc123 \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import ( @@ -1001,7 +1001,7 @@ async def compact_response( ```bash curl -X POST http://localhost:4000/v1/responses/compact \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-4o", "input": [{"role": "user", "content": "Hello"}] @@ -1153,7 +1153,7 @@ async def responses_input_tokens( ```bash curl -X POST http://localhost:4000/v1/responses/input_tokens \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "model": "gpt-4o", "input": "Hello, how are you?" @@ -1232,11 +1232,11 @@ async def cancel_response( ```bash # Cancel polling response curl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" # Cancel provider response curl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import ( diff --git a/litellm/proxy/search_endpoints/endpoints.py b/litellm/proxy/search_endpoints/endpoints.py index 9cc76024770..349eb5b7861 100644 --- a/litellm/proxy/search_endpoints/endpoints.py +++ b/litellm/proxy/search_endpoints/endpoints.py @@ -58,7 +58,7 @@ async def search( Example with search_tool_name in URL (recommended - keeps body Perplexity-compatible): ```bash curl -X POST "http://localhost:4000/v1/search/litellm-search" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "latest AI developments 2024", @@ -71,7 +71,7 @@ async def search( Example with search_tool_name in body: ```bash curl -X POST "http://localhost:4000/v1/search" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "search_tool_name": "litellm-search", @@ -270,7 +270,7 @@ async def list_search_tools( Example: ```bash curl -X GET "http://localhost:4000/v1/search/tools" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Response: diff --git a/litellm/proxy/spend_tracking/spend_management_endpoints.py b/litellm/proxy/spend_tracking/spend_management_endpoints.py index 48cc684549f..7c54e154650 100644 --- a/litellm/proxy/spend_tracking/spend_management_endpoints.py +++ b/litellm/proxy/spend_tracking/spend_management_endpoints.py @@ -437,7 +437,7 @@ async def spend_key_fn( Example Request: ``` curl -X GET "http://0.0.0.0:8000/spend/keys" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ @@ -505,13 +505,13 @@ async def spend_user_fn( Example Request: ``` curl -X GET "http://0.0.0.0:8000/spend/users" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` View User Table row for user_id ``` curl -X GET "http://0.0.0.0:8000/spend/users?user_id=1234" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import prisma_client @@ -576,13 +576,13 @@ async def view_spend_tags( Example Request: ``` curl -X GET "http://0.0.0.0:8000/spend/tags" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Spend with Start Date and End Date ``` curl -X GET "http://0.0.0.0:8000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ @@ -1238,7 +1238,7 @@ async def get_spend_capture_rate( Example: ``` - curl -H "Authorization: Bearer sk-1234" \ + curl -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ "http://localhost:4000/spend/capture_rate?provider=openai&start_date=2026-09-17&end_date=2026-09-23" ``` """ @@ -2158,13 +2158,13 @@ async def global_view_spend_tags( Example Request: ``` curl -X GET "http://0.0.0.0:4000/spend/tags" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Spend with Start Date and End Date ``` curl -X GET "http://0.0.0.0:4000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ import traceback @@ -2308,7 +2308,7 @@ async def calculate_spend(request: SpendCalculateRequest): ``` curl --location 'http://localhost:4000/spend/calculate' - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ "model": "anthropic.claude-v2", @@ -2320,7 +2320,7 @@ async def calculate_spend(request: SpendCalculateRequest): ``` curl --location 'http://localhost:4000/spend/calculate' - --header 'Authorization: Bearer sk-1234' + --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ "completion_response": { @@ -2594,7 +2594,7 @@ async def ui_view_spend_logs( Example: ``` curl -X GET "http://0.0.0.0:8000/spend/logs/v2?start_date=2025-11-25%2000:00:00&end_date=2025-11-26%2023:59:59&page=1&page_size=50" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import prisma_client @@ -3506,31 +3506,31 @@ async def view_spend_logs( Example Request for all logs ``` curl -X GET "http://0.0.0.0:8000/spend/logs" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example Request for specific request_id ``` curl -X GET "http://0.0.0.0:8000/spend/logs?request_id=chatcmpl-6dcb2540-d3d7-4e49-bb27-291f863f112e" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example Request for specific api_key ``` curl -X GET "http://0.0.0.0:8000/spend/logs?api_key=d5345c0ecc68ae6295c69f91926b2bd379e25481a40c34b5884d157a9f65d8fa" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example Request for specific user_id ``` curl -X GET "http://0.0.0.0:8000/spend/logs?user_id=ishaan@berri.ai" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example Request for date range with individual logs (unsummarized) ``` curl -X GET "http://0.0.0.0:8000/spend/logs?start_date=2024-01-01&end_date=2024-01-02&summarize=false" \ --H "Authorization: Bearer sk-1234" +-H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import prisma_client @@ -4304,7 +4304,7 @@ async def provider_budgets() -> ProviderBudgetResponse: ```bash curl -X GET http://localhost:4000/provider/budgets \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` Example Response diff --git a/litellm/proxy/vector_store_endpoints/endpoints.py b/litellm/proxy/vector_store_endpoints/endpoints.py index f21c294e5a2..b67219def38 100644 --- a/litellm/proxy/vector_store_endpoints/endpoints.py +++ b/litellm/proxy/vector_store_endpoints/endpoints.py @@ -561,7 +561,7 @@ async def index_create( ```bash curl -L -X POST 'http://0.0.0.0:4000/v1/indexes' \ -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer sk-1234' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -d '{ "index_name": "dall-e-3", "litellm_params": { @@ -622,7 +622,7 @@ async def index_list( ```bash curl -L -X GET 'http://0.0.0.0:4000/v1/indexes' \ - -H 'Authorization: Bearer sk-1234' + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import prisma_client diff --git a/litellm/proxy/video_endpoints/endpoints.py b/litellm/proxy/video_endpoints/endpoints.py index fe966c2e31a..9175d067920 100644 --- a/litellm/proxy/video_endpoints/endpoints.py +++ b/litellm/proxy/video_endpoints/endpoints.py @@ -57,7 +57,7 @@ async def video_generation( Example: ```bash curl -X POST "http://localhost:4000/v1/videos" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "sora-2", @@ -144,7 +144,7 @@ async def video_list( Example: ```bash curl -X GET "http://localhost:4000/v1/videos" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import ( @@ -232,7 +232,7 @@ async def video_status( Example: ```bash curl -X GET "http://localhost:4000/v1/videos/video_123" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import ( @@ -332,7 +332,7 @@ async def video_content( Example: ```bash curl -X GET "http://localhost:4000/v1/videos/{video_id}/content" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ --output video.mp4 ``` """ @@ -437,7 +437,7 @@ async def video_remix( Example: ```bash curl -X POST "http://localhost:4000/v1/videos/video_123/remix" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "A new version with different colors" @@ -541,7 +541,7 @@ async def video_create_character( Example: ```bash curl -X POST "http://localhost:4000/v1/videos/characters" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -F "video=@character_video.mp4" \ -F "name=my_character" ``` @@ -643,7 +643,7 @@ async def video_get_character( Example: ```bash curl -X GET "http://localhost:4000/v1/videos/characters/char_123" \ - -H "Authorization: Bearer sk-1234" + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` """ from litellm.proxy.proxy_server import ( @@ -748,7 +748,7 @@ async def video_edit( Example: ```bash curl -X POST "http://localhost:4000/v1/videos/edits" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{"prompt": "Make it brighter", "video": {"id": "video_123"}}' ``` @@ -852,7 +852,7 @@ async def video_extension( Example: ```bash curl -X POST "http://localhost:4000/v1/videos/extensions" \ - -H "Authorization: Bearer sk-1234" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{"prompt": "Continue the scene", "seconds": "5", "video": {"id": "video_123"}}' ``` diff --git a/qa_sticky_session.sh b/qa_sticky_session.sh index 326bb8117c7..2c5a1a66c4c 100755 --- a/qa_sticky_session.sh +++ b/qa_sticky_session.sh @@ -1,14 +1,14 @@ #!/usr/bin/env bash # QA: code interpreter sandbox stickiness via metadata.session_id # bash qa_sticky_session.sh -# LITELLM_BASE_URL=http://localhost:4000 LITELLM_KEY=sk-1234 bash qa_sticky_session.sh +# LITELLM_BASE_URL=http://localhost:4000 LITELLM_KEY="$LITELLM_MASTER_KEY" bash qa_sticky_session.sh set -euo pipefail BASE="${LITELLM_BASE_URL:-http://localhost:4000}" -KEY="${LITELLM_KEY:-sk-1234}" +KEY="${LITELLM_KEY:-${LITELLM_MASTER_KEY:?set LITELLM_KEY or LITELLM_MASTER_KEY}}" MODEL="${LITELLM_MODEL:-gpt-4o-mini}" -# proxy running at http://localhost:4000 (master key: sk-1234) +# proxy running at http://localhost:4000 SESSION_A="qa-session-$(date +%s)-A" SESSION_B="qa-session-$(date +%s)-B" diff --git a/scripts/adaptive_router_demo/chat.html b/scripts/adaptive_router_demo/chat.html index 9e7237847c0..c9943321bba 100644 --- a/scripts/adaptive_router_demo/chat.html +++ b/scripts/adaptive_router_demo/chat.html @@ -366,7 +366,7 @@
- + diff --git a/scripts/adaptive_router_demo/dashboard.html b/scripts/adaptive_router_demo/dashboard.html index 6652aa19805..2f3f36de872 100644 --- a/scripts/adaptive_router_demo/dashboard.html +++ b/scripts/adaptive_router_demo/dashboard.html @@ -255,7 +255,7 @@
- + diff --git a/scripts/adaptive_router_demo/eval.py b/scripts/adaptive_router_demo/eval.py index b02e4a37d31..a9a8a7bc71c 100644 --- a/scripts/adaptive_router_demo/eval.py +++ b/scripts/adaptive_router_demo/eval.py @@ -11,7 +11,7 @@ For each test case: Run: uv run python scripts/adaptive_router_demo/eval.py \ --proxy-url http://localhost:4000 \ - --api-key sk-1234 \ + --api-key "$LITELLM_MASTER_KEY" \ --router smart-cheap-router \ --judge-model smart """ diff --git a/scripts/adaptive_router_demo/traffic.py b/scripts/adaptive_router_demo/traffic.py index eae5506eaee..5ff806ef5a6 100644 --- a/scripts/adaptive_router_demo/traffic.py +++ b/scripts/adaptive_router_demo/traffic.py @@ -23,7 +23,7 @@ Why this shape: Run: uv run python scripts/adaptive_router_demo/traffic.py \\ --proxy-url http://localhost:4000 \\ - --api-key sk-1234 \\ + --api-key "$LITELLM_MASTER_KEY" \\ --router smart-cheap-router \\ --rounds 100 \\ --rate 0.5 diff --git a/scripts/benchmark_anthropic_messages_perf.py b/scripts/benchmark_anthropic_messages_perf.py index 3e4b4b25b6a..3639e5ef326 100644 --- a/scripts/benchmark_anthropic_messages_perf.py +++ b/scripts/benchmark_anthropic_messages_perf.py @@ -35,13 +35,12 @@ import tempfile import time from dataclasses import dataclass from pathlib import Path -from typing import Any, Optional +from typing import Any, Final, Optional import aiohttp from aiohttp import web DEFAULT_MODEL = "claude-perf-test" -DEFAULT_API_KEY = "sk-1234" @dataclass @@ -490,7 +489,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--proxy-port", type=int, default=4000) parser.add_argument("--provider-host", default="127.0.0.1") parser.add_argument("--provider-port", type=int, default=8098) - parser.add_argument("--api-key", default=DEFAULT_API_KEY) + parser.add_argument("--api-key", default=os.environ.get("LITELLM_MASTER_KEY")) parser.add_argument("--requests", type=int, default=300) parser.add_argument("--concurrency", type=int, default=20) parser.add_argument("--warmup", type=int, default=30) @@ -524,12 +523,23 @@ def parse_args() -> argparse.Namespace: async def async_main() -> None: args = parse_args() + if args.no_start_proxy and not args.api_key: + raise ValueError("Set LITELLM_MASTER_KEY or pass --api-key when using --no-start-proxy") + api_key: Final = args.api_key or ( + "sk-" + + subprocess.run( + ["openssl", "rand", "-hex", "16"], + capture_output=True, + check=True, + text=True, + ).stdout.strip() + ) litellm_dir = Path(args.litellm_dir).resolve() revision = get_git_revision(litellm_dir) proxy_base_url = f"http://{args.proxy_host}:{args.proxy_port}" proxy_url = f"{proxy_base_url}/v1/messages" headers = { - "Authorization": f"Bearer {args.api_key}", + "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } stream_payload = { @@ -557,7 +567,7 @@ async def async_main() -> None: provider_base_url = provider.base_url config_path = tmp_dir / "config.yaml" - write_proxy_config(config_path, provider_base_url, args.api_key) + write_proxy_config(config_path, provider_base_url, api_key) try: if not args.no_start_proxy: diff --git a/scripts/benchmark_chat_completions_perf.py b/scripts/benchmark_chat_completions_perf.py index c9f025a145f..61f04836cac 100644 --- a/scripts/benchmark_chat_completions_perf.py +++ b/scripts/benchmark_chat_completions_perf.py @@ -29,14 +29,13 @@ import tempfile import time from dataclasses import dataclass from pathlib import Path -from typing import Any, Optional +from typing import Any, Final, Optional import aiohttp from aiohttp import web DEFAULT_MODEL = "perf-test-model" -DEFAULT_API_KEY = "sk-1234" @dataclass @@ -646,7 +645,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--proxy-port", type=int, default=4000) parser.add_argument("--provider-host", default="127.0.0.1") parser.add_argument("--provider-port", type=int, default=8099) - parser.add_argument("--api-key", default=DEFAULT_API_KEY) + parser.add_argument("--api-key", default=os.environ.get("LITELLM_MASTER_KEY")) parser.add_argument("--requests", type=int, default=500) parser.add_argument("--concurrency", type=int, default=100) parser.add_argument("--stream-requests", type=int, default=200) @@ -695,12 +694,23 @@ def parse_args() -> argparse.Namespace: async def async_main() -> None: args = parse_args() + if args.no_start_proxy and not args.api_key: + raise ValueError("Set LITELLM_MASTER_KEY or pass --api-key when using --no-start-proxy") + api_key: Final = args.api_key or ( + "sk-" + + subprocess.run( + ["openssl", "rand", "-hex", "16"], + capture_output=True, + check=True, + text=True, + ).stdout.strip() + ) litellm_dir = Path(args.litellm_dir).resolve() revision = get_git_revision(litellm_dir) proxy_base_url = f"http://{args.proxy_host}:{args.proxy_port}" proxy_url = f"{proxy_base_url}/v1/chat/completions" headers = { - "Authorization": f"Bearer {args.api_key}", + "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } provider_headers = { @@ -732,7 +742,7 @@ async def async_main() -> None: provider_base_url = provider.base_url config_path = tmp_dir / "config.yaml" - write_proxy_config(config_path, provider_base_url, args.api_key) + write_proxy_config(config_path, provider_base_url, api_key) try: if not args.no_start_proxy: diff --git a/scripts/benchmark_mock.py b/scripts/benchmark_mock.py index 55dbb1d4134..93a2e05ec03 100644 --- a/scripts/benchmark_mock.py +++ b/scripts/benchmark_mock.py @@ -3,6 +3,7 @@ import argparse import asyncio +import os import time import statistics @@ -17,7 +18,7 @@ REQUEST_BODY = { } HEADERS = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } diff --git a/scripts/benchmark_proxy_vs_provider.py b/scripts/benchmark_proxy_vs_provider.py index 6196580b230..28d9d0c9cc7 100755 --- a/scripts/benchmark_proxy_vs_provider.py +++ b/scripts/benchmark_proxy_vs_provider.py @@ -9,7 +9,7 @@ USAGE EXAMPLES: # Set required environment variables export LITELLM_PROXY_URL='http://localhost:4000/chat/completions' export PROVIDER_URL='https://api.openai.com/v1/chat/completions' - export LITELLM_PROXY_API_KEY='sk-1234' + export LITELLM_PROXY_API_KEY="$LITELLM_MASTER_KEY" export PROVIDER_API_KEY='sk-openai-key' # Run from scripts directory @@ -537,7 +537,7 @@ Examples: # 1. Basic usage (recommended - sequential execution) export LITELLM_PROXY_URL='http://localhost:4000/chat/completions' export PROVIDER_URL='https://api.openai.com/v1/chat/completions' - export LITELLM_PROXY_API_KEY='sk-1234' + export LITELLM_PROXY_API_KEY="$LITELLM_MASTER_KEY" export PROVIDER_API_KEY='sk-openai-key' python scripts/benchmark_proxy_vs_provider.py diff --git a/scripts/health_check/health_check_client.py b/scripts/health_check/health_check_client.py index 9ef8b934961..5fc0451b2d9 100644 --- a/scripts/health_check/health_check_client.py +++ b/scripts/health_check/health_check_client.py @@ -400,7 +400,7 @@ class LiteLLMHealthCheckClient: async def main(): """Main entry point.""" base_url = os.environ.get("LITELLM_BASE_URL", "http://localhost:4000") - api_key = os.environ.get("LITELLM_API_KEY", "sk-1234") + api_key = os.environ["LITELLM_API_KEY"] yaml_path = os.environ.get("LITELLM_MODELS_YAML") custom_auth_header = os.environ.get( "LITELLM_CUSTOM_AUTH_HEADER" diff --git a/scripts/health_check/run_parallel_health_checks.ps1 b/scripts/health_check/run_parallel_health_checks.ps1 index 850fc6baab6..13b5a994835 100644 --- a/scripts/health_check/run_parallel_health_checks.ps1 +++ b/scripts/health_check/run_parallel_health_checks.ps1 @@ -4,7 +4,7 @@ # # Usage: # $env:LITELLM_BASE_URL="https://litellm.example.com" -# $env:LITELLM_API_KEY="your-api-key" +# $env:LITELLM_API_KEY="" # .\run_parallel_health_checks.ps1 [num_parallel_jobs] [image_name] # # Defaults: @@ -17,15 +17,14 @@ param( [string]$ContainerRuntime = "docker" ) -# Set defaults for environment variables if not provided +# Require credentials for the target proxy if (-not $env:LITELLM_BASE_URL) { $env:LITELLM_BASE_URL = "https://litellm-perf-cache-and-router.onrender.com" Write-Warning "LITELLM_BASE_URL not set, using default: $env:LITELLM_BASE_URL" } if (-not $env:LITELLM_API_KEY) { - $env:LITELLM_API_KEY = "sk-1234" - Write-Warning "LITELLM_API_KEY not set, using default: $env:LITELLM_API_KEY" + throw "LITELLM_API_KEY must be set" } # Check if container runtime is available diff --git a/scripts/health_check/run_parallel_health_checks.sh b/scripts/health_check/run_parallel_health_checks.sh index d1913e3fdd6..aee902ff290 100644 --- a/scripts/health_check/run_parallel_health_checks.sh +++ b/scripts/health_check/run_parallel_health_checks.sh @@ -5,7 +5,7 @@ # # Usage: # export LITELLM_BASE_URL="https://litellm.example.com" -# export LITELLM_API_KEY="your-api-key" +# export LITELLM_API_KEY="" # ./run_parallel_health_checks.sh [num_parallel_jobs] [image_name] [container_runtime] # # Defaults: @@ -20,16 +20,13 @@ NUM_PARALLEL_JOBS="${1:-16}" IMAGE_NAME="${2:-litellm/litellm-health-check:latest}" CONTAINER_RUNTIME="${3:-docker}" -# Set defaults for environment variables if not provided +# Require credentials for the target proxy if [ -z "$LITELLM_BASE_URL" ]; then export LITELLM_BASE_URL="https://litellm-perf-cache-and-router.onrender.com" echo "Warning: LITELLM_BASE_URL not set, using default: $LITELLM_BASE_URL" >&2 fi -if [ -z "$LITELLM_API_KEY" ]; then - export LITELLM_API_KEY="sk-1234" - echo "Warning: LITELLM_API_KEY not set, using default: $LITELLM_API_KEY" >&2 -fi +: "${LITELLM_API_KEY:?set LITELLM_API_KEY}" # Check if container runtime is available if ! command -v "$CONTAINER_RUNTIME" &> /dev/null; then diff --git a/scripts/lens_dev.sh b/scripts/lens_dev.sh index 1add480c227..69ef8c0f8bd 100755 --- a/scripts/lens_dev.sh +++ b/scripts/lens_dev.sh @@ -116,7 +116,6 @@ proxy_env() { export LENS_WORKER_IMAGE=litellm-lens-worker:local export LITELLM_MODE=PRODUCTION export LITELLM_MASTER_KEY="$master_key" - if [ "$master_key" = sk-1234 ]; then export LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true; fi export LITELLM_SALT_KEY=sk-local-tracing-salt-key export DATABASE_URL="$database_url" export STORE_MODEL_IN_DB=True diff --git a/tests/_master_key.py b/tests/_master_key.py new file mode 100644 index 00000000000..488cdf554c5 --- /dev/null +++ b/tests/_master_key.py @@ -0,0 +1,11 @@ +import hashlib +import os +import secrets +from typing import Final + +_xdist_test_run_uid: Final = os.environ.get("PYTEST_XDIST_TESTRUNUID") +MASTER_KEY: Final = ( + f"sk-{hashlib.sha256(_xdist_test_run_uid.encode()).hexdigest()[:32]}" + if _xdist_test_run_uid is not None + else f"sk-{secrets.token_hex(16)}" +) diff --git a/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py b/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py index d2d789fb0c7..b6acfea44f6 100644 --- a/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py +++ b/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py @@ -5,6 +5,7 @@ This test ensures that the proxy starts and serves requests even with a bad lice in ci/cd config.yml, we set the license to "bad-license" """ +import os import pytest import aiohttp from typing import Optional @@ -36,7 +37,7 @@ async def test_health_and_chat_completion(): # Make a chat completion call url = "http://0.0.0.0:4000/chat/completions" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } data = { diff --git a/tests/code_coverage_tests/check_no_publicly_known_master_key.py b/tests/code_coverage_tests/check_no_publicly_known_master_key.py new file mode 100644 index 00000000000..d8c7291de29 --- /dev/null +++ b/tests/code_coverage_tests/check_no_publicly_known_master_key.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import os +import subprocess +import sys +from collections.abc import Iterator +from pathlib import Path +from typing import Final + +REPO_ROOT: Final = Path(__file__).resolve().parents[2] +PUBLICLY_KNOWN_MASTER_KEY_PREFIX: Final = "sk-" + "1234" + + +def _file_violations(relative_path: str) -> tuple[str, ...]: + path: Final = REPO_ROOT / relative_path + if path.is_dir(): + return () + try: + contents: Final = path.read_bytes() + except FileNotFoundError: + return () + if b"\0" in contents: + return () + try: + text: Final = contents.decode("utf-8") + except UnicodeDecodeError: + return () + return tuple( + f"{relative_path}:{line_number}" + for line_number, line in enumerate(text.splitlines(), start=1) + if PUBLICLY_KNOWN_MASTER_KEY_PREFIX in line + ) + + +def _violations(tracked_paths: tuple[str, ...]) -> Iterator[str]: + for path in tracked_paths: + yield from _file_violations(path) + + +def main() -> int: + result: Final = subprocess.run( + ["git", "-C", os.fspath(REPO_ROOT), "ls-files", "-z"], + check=True, + stdout=subprocess.PIPE, + ) + tracked_paths: Final = tuple( + os.fsdecode(path) for path in result.stdout.split(b"\0") if path + ) + violations: Final = tuple(_violations(tracked_paths)) + for violation in violations: + print(violation) + if violations: + print(f"\n{len(violations)} tracked line(s) contain the publicly known master key prefix") + return 1 + print("No tracked files contain the publicly known master key prefix") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/code_coverage_tests/test_e2e_metadata.py b/tests/code_coverage_tests/test_e2e_metadata.py index b1612d3d259..a23e5c57bf0 100644 --- a/tests/code_coverage_tests/test_e2e_metadata.py +++ b/tests/code_coverage_tests/test_e2e_metadata.py @@ -533,7 +533,7 @@ class TestSecretMasking: environ: Final = { "OPENAI_API_KEY": "sk-proj-0123456789", "AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG", - "LITELLM_MASTER_KEY": "sk-1234", + "LITELLM_MASTER_KEY": "sk-test", "GOOGLE_APPLICATION_CREDENTIALS": "/secrets/vertex.json", "KEYCLOAK_URL": "http://localhost:8080", "E2E_MODEL": "claude-haiku-4-5", diff --git a/tests/e2e/CONTRIBUTING.md b/tests/e2e/CONTRIBUTING.md index 682bf41d7d9..183b382f634 100644 --- a/tests/e2e/CONTRIBUTING.md +++ b/tests/e2e/CONTRIBUTING.md @@ -13,10 +13,10 @@ The suites run against a live proxy, so bring one up first by running the litell ## Running the tests locally -1. Create a `.env` file in this directory with the provider keys the example models use, plus the master key and the Postgres/Redis coordinates your config reads back: +1. Generate a master key with `export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 32)"`. Create a `.env` file in this directory with the provider keys the example models use and the Postgres/Redis coordinates your config reads back: ```bash - LITELLM_MASTER_KEY="sk-1234" + LITELLM_MASTER_KEY="sk-" DATABASE_URL="postgresql://llmproxy:dbpassword9090@localhost:5432/litellm" REDIS_HOST="localhost" REDIS_PORT="6379" @@ -110,7 +110,7 @@ A couple of logging destinations are configured on the proxy rather than by the ```bash bash tests/e2e/secret_manager/backend.sh up cyberark (set -a; . ~/.cache/litellm-e2e-secret-manager/cyberark/proxy.env; set +a; env -u OPENAI_API_KEY LITELLM_LICENSE=... \ - LITELLM_MASTER_KEY=sk-1234 DATABASE_URL=... uv run litellm --config tests/e2e/gateway/secret_manager_cyberark_ci_config.yml --port 4000) + LITELLM_MASTER_KEY="$LITELLM_MASTER_KEY" DATABASE_URL=... uv run litellm --config tests/e2e/gateway/secret_manager_cyberark_ci_config.yml --port 4000) (set -a; . ~/.cache/litellm-e2e-secret-manager/cyberark/tests.env; set +a; OPENAI_API_KEY=... \ uv run --group e2e-dev pytest tests/e2e/secret_manager/ -v) bash tests/e2e/secret_manager/backend.sh down cyberark diff --git a/tests/e2e/claude_code/cron_vm/run_daily.sh b/tests/e2e/claude_code/cron_vm/run_daily.sh index af01057eff7..f40bd5c0be2 100755 --- a/tests/e2e/claude_code/cron_vm/run_daily.sh +++ b/tests/e2e/claude_code/cron_vm/run_daily.sh @@ -51,7 +51,7 @@ set -Eeuo pipefail LITELLM_REPO="${LITELLM_REPO:-${HOME}/litellm/litellm}" WORKTREE="${LITELLM_WORKTREE:-${HOME}/litellm-cron-worktree}" PROXY_PORT="${PROXY_PORT:-4100}" -PROXY_API_KEY="${PROXY_API_KEY:-sk-cron-matrix}" +PROXY_API_KEY="${PROXY_API_KEY:-sk-$(openssl rand -hex 16)}" DOCS_REPO="${DOCS_REPO:-BerriAI/litellm-docs}" DOCS_BRANCH="${DOCS_BRANCH:-main}" DOCS_TARGET_PATH="${DOCS_TARGET_PATH:-src/data/compatibility-matrix.json}" @@ -347,9 +347,8 @@ log "starting proxy on 127.0.0.1:${PROXY_PORT}" # exclusively by the pytest run on the same host (the health check and # the test env set `LITELLM_PROXY_URL=http://127.0.0.1:...`), # so there's no reason to expose it on the container's external interfaces. -# Without `--host`, `litellm` defaults to 0.0.0.0, which combined with -# the predictable default `LITELLM_MASTER_KEY=sk-cron-matrix` would -# allow anything that can reach :${PROXY_PORT} on the host to authenticate +# Without `--host`, `litellm` defaults to 0.0.0.0, so a predictable proxy key +# would allow anything that can reach :${PROXY_PORT} on the host to authenticate # and burn upstream provider credentials. # # `setsid` puts the proxy in its own session+pgroup so cleanup() can diff --git a/tests/e2e/claude_code/run_compat.sh b/tests/e2e/claude_code/run_compat.sh index b881cf1d31e..c42416283e7 100755 --- a/tests/e2e/claude_code/run_compat.sh +++ b/tests/e2e/claude_code/run_compat.sh @@ -13,7 +13,7 @@ # # Required env (proxy connection), same names as the rest of tests/e2e: # LITELLM_PROXY_URL e.g. http://localhost:4000 -# LITELLM_MASTER_KEY e.g. sk-1234 +# LITELLM_MASTER_KEY e.g. sk- # # Optional env (rate limits, all default to 5 req/s; 0 disables a column): # LITELLM_COMPAT_RATE_ANTHROPIC diff --git a/tests/e2e/e2e_config.py b/tests/e2e/e2e_config.py index e88bfad8388..8a332aa8f24 100644 --- a/tests/e2e/e2e_config.py +++ b/tests/e2e/e2e_config.py @@ -25,7 +25,7 @@ from pydantic import TypeAdapter load_dotenv(Path(__file__).resolve().parent / ".env", override=False) PROXY_BASE_URL = os.environ.get("LITELLM_PROXY_URL", "http://localhost:4000").rstrip("/") -MASTER_KEY = os.environ.get("LITELLM_MASTER_KEY", "sk-1234") +MASTER_KEY = os.environ["LITELLM_MASTER_KEY"] # Control-plane (management/admin) base URL. Defaults to PROXY_BASE_URL so a # single path-routing host (stage ALB, compose monolith) works for both planes. diff --git a/tests/e2e/migrations/lens_compose_smoke.sh b/tests/e2e/migrations/lens_compose_smoke.sh index 6a57926895b..e091b007954 100644 --- a/tests/e2e/migrations/lens_compose_smoke.sh +++ b/tests/e2e/migrations/lens_compose_smoke.sh @@ -15,7 +15,7 @@ if worker_image > /dev/null 2>&1; then fi qa_dir=$(mktemp -d) -master_key="sk-$(openssl rand -hex 32)" +master_key="sk-$(openssl rand -hex 16)" compose=(docker compose -p lens-compose-ci --env-file "$qa_dir/env" -f deploy/lens/stack.yaml) cleanup() { "${compose[@]}" --profile lens down -v --remove-orphans >/dev/null 2>&1 || true diff --git a/tests/e2e/other/owned_jwt_gateway.py b/tests/e2e/other/owned_jwt_gateway.py index 1af348cac60..b6c31479bd2 100644 --- a/tests/e2e/other/owned_jwt_gateway.py +++ b/tests/e2e/other/owned_jwt_gateway.py @@ -86,7 +86,6 @@ def owned_jwt_gateway( "JWT_PUBLIC_KEY_URL": idp.jwks_url, "JWT_ISSUER": idp.issuer, "JWT_AUDIENCE": "litellm-e2e", - "LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY": "true", "DISABLE_SCHEMA_UPDATE": "true", "STORE_MODEL_IN_DB": "True", "PYTHONPATH": str(Path(__file__).resolve().parents[3]), diff --git a/tests/e2e/test_fixture_canonical.py b/tests/e2e/test_fixture_canonical.py index 8890848522c..7bc7d7462ab 100644 --- a/tests/e2e/test_fixture_canonical.py +++ b/tests/e2e/test_fixture_canonical.py @@ -58,7 +58,7 @@ class TestPlaceholders: ("file-XyZ12345abc", ""), ("gpt-4o-mini", "gpt-4o-mini"), ("max_tokens", "max_tokens"), - ("sk-1234", "sk-1234"), + ("sk-9876", "sk-9876"), ], ) def test_rewrites_exactly_the_volatile_shapes(self, raw: str, expected: str) -> None: diff --git a/tests/e2e/ui/fixtures/users.ts b/tests/e2e/ui/fixtures/users.ts index 0457361d9d4..1c8b7b7a32d 100644 --- a/tests/e2e/ui/fixtures/users.ts +++ b/tests/e2e/ui/fixtures/users.ts @@ -6,6 +6,7 @@ import { INTERNAL_VIEWER_STORAGE_PATH, TEAM_ADMIN_STORAGE_PATH, } from "../constants"; +import { masterKey } from "../helpers/traffic"; export enum Role { ProxyAdmin = "proxy_admin", @@ -20,7 +21,7 @@ export type SeedApiRole = "proxy_admin_viewer" | "internal_user" | "internal_use export const users: Record = { [Role.ProxyAdmin]: { email: "admin", - password: process.env.LITELLM_MASTER_KEY || "sk-1234", + password: masterKey(), }, [Role.ProxyAdminViewer]: { email: "adminviewer@test.local", diff --git a/tests/e2e/ui/globalSetup.ts b/tests/e2e/ui/globalSetup.ts index 8b3ad204767..d97789c227e 100644 --- a/tests/e2e/ui/globalSetup.ts +++ b/tests/e2e/ui/globalSetup.ts @@ -3,6 +3,7 @@ import { users, Role, STORAGE_PATHS } from "./fixtures/users"; import { ARTIFACT_DIR, UI_BASE_URL } from "./constants"; import { expectUnrestrictedDashboard, setInvitedUserPassword } from "./helpers/userOnboarding"; import { hideLiteAdmin } from "./helpers/navigation"; +import { masterKey as getMasterKey } from "./helpers/traffic"; import * as fs from "fs"; import * as path from "path"; @@ -22,7 +23,7 @@ async function globalSetup() { // enable_projects_ui setting is on, and the seeded DB starts with it off. // The proxy runs with LITELLM_LICENSE in CI, so enable it the same way // the admin UI toggle does; the projects migration smoke needs the link. - const masterKey = process.env.LITELLM_MASTER_KEY || "sk-1234"; + const masterKey = getMasterKey(); const api = await request.newContext(); const settingsRes = await api.patch(`${UI_BASE_URL}${rootPath}/update/ui_settings`, { headers: { Authorization: `Bearer ${masterKey}` }, diff --git a/tests/e2e/ui/helpers/traffic.ts b/tests/e2e/ui/helpers/traffic.ts index b534c475221..da02f24f408 100644 --- a/tests/e2e/ui/helpers/traffic.ts +++ b/tests/e2e/ui/helpers/traffic.ts @@ -11,7 +11,13 @@ export const DEPLOYMENT_MODEL_B = "openai/fake-claude"; /** The only completion text fixtures/mock_llm_server/server.py ever returns. */ export const MOCK_RESPONSE_TEXT = "This is a mock response."; -export const masterKey = (): string => process.env.LITELLM_MASTER_KEY || "sk-1234"; +export const masterKey = (): string => { + const key = process.env.LITELLM_MASTER_KEY; + if (!key) { + throw new Error("LITELLM_MASTER_KEY must be set"); + } + return key; +}; export const rootPath = (): string => process.env.SERVER_ROOT_PATH ?? ""; diff --git a/tests/e2e/ui/run_e2e.sh b/tests/e2e/ui/run_e2e.sh index 5c367ba0024..97cbe5fcf59 100755 --- a/tests/e2e/ui/run_e2e.sh +++ b/tests/e2e/ui/run_e2e.sh @@ -144,8 +144,7 @@ else fi # --- Credentials --- -export LITELLM_MASTER_KEY="sk-1234" -export LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY="true" +export LITELLM_MASTER_KEY="${LITELLM_MASTER_KEY:-sk-$(openssl rand -hex 16)}" export MOCK_LLM_URL="http://127.0.0.1:${MOCK_LLM_PORT}/v1" export E2E_MOCK_PRESIDIO_URL="http://127.0.0.1:${MOCK_PRESIDIO_PORT}" export DISABLE_SCHEMA_UPDATE="true" diff --git a/tests/e2e/ui/tests/integrationCritical/costOptimizationModelGroups.spec.ts b/tests/e2e/ui/tests/integrationCritical/costOptimizationModelGroups.spec.ts index 08dcc4c2c21..b86931d8a80 100644 --- a/tests/e2e/ui/tests/integrationCritical/costOptimizationModelGroups.spec.ts +++ b/tests/e2e/ui/tests/integrationCritical/costOptimizationModelGroups.spec.ts @@ -4,11 +4,12 @@ import { execFileSync } from "node:child_process"; import * as path from "node:path"; import { Page } from "../../fixtures/pages"; import { navigateToPage } from "../../helpers/navigation"; +import { masterKey } from "../../helpers/traffic"; test("cache leakage by model merges a deployment's resolved and requested model names into its model group", async ({ page, }) => { - const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; + const master = masterKey(); const marker = `integration-browser-${randomUUID()}`; const group = `${marker}-public`; const deployment = `${marker}-backend`; diff --git a/tests/e2e/ui/tests/integrationCritical/logsDrawerCredentialCanary.spec.ts b/tests/e2e/ui/tests/integrationCritical/logsDrawerCredentialCanary.spec.ts index 1d86dee107d..d2346e107ef 100644 --- a/tests/e2e/ui/tests/integrationCritical/logsDrawerCredentialCanary.spec.ts +++ b/tests/e2e/ui/tests/integrationCritical/logsDrawerCredentialCanary.spec.ts @@ -2,6 +2,7 @@ import { test, expect, type APIRequestContext } from "@playwright/test"; import { randomUUID } from "node:crypto"; import { Page } from "../../fixtures/pages"; import { dismissFeedbackPopup, navigateToPage } from "../../helpers/navigation"; +import { masterKey } from "../../helpers/traffic"; /** * Credential canary S8: what the Logs page renders for a request, including any client-side @@ -55,7 +56,7 @@ test("the Logs drawer renders the stored request without the deployment api_key" page, request, }) => { - const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; + const master = masterKey(); const upstream = ( process.env.INTEGRATION_UPSTREAM_URL ?? "http://127.0.0.1:8190" ).replace(/\/+$/, ""); diff --git a/tests/e2e/ui/tests/integrationCritical/mcpUserEnvVars.spec.ts b/tests/e2e/ui/tests/integrationCritical/mcpUserEnvVars.spec.ts index 3572e520ae9..11cc1c948a3 100644 --- a/tests/e2e/ui/tests/integrationCritical/mcpUserEnvVars.spec.ts +++ b/tests/e2e/ui/tests/integrationCritical/mcpUserEnvVars.spec.ts @@ -9,8 +9,9 @@ import { randomUUID } from "node:crypto"; import { Page } from "../../fixtures/pages"; import { navigateToPage } from "../../helpers/navigation"; import { captureRequestBody } from "../../helpers/roundTrip"; +import { masterKey } from "../../helpers/traffic"; -const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; +const master = masterKey(); const headers = { Authorization: `Bearer ${master}` }; const TOKEN = "USER_TOKEN"; diff --git a/tests/e2e/ui/tests/integrationCritical/projectDetachment.spec.ts b/tests/e2e/ui/tests/integrationCritical/projectDetachment.spec.ts index b7b0a395dd1..497c2a6914f 100644 --- a/tests/e2e/ui/tests/integrationCritical/projectDetachment.spec.ts +++ b/tests/e2e/ui/tests/integrationCritical/projectDetachment.spec.ts @@ -5,12 +5,13 @@ import * as path from "node:path"; import { Page } from "../../fixtures/pages"; import { navigateToPage, openKeyDetail } from "../../helpers/navigation"; import { captureRequestBody, readBack } from "../../helpers/roundTrip"; +import { masterKey } from "../../helpers/traffic"; test("project creation and explicit detachment preserve saved scope and restore serving", async ({ page, request, }) => { - const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; + const master = masterKey(); const headers = { Authorization: `Bearer ${master}` }; const prefix = `integration-browser-${randomUUID()}`; // rebind-ok: Register cleanup after each acquisition so partial setup always unwinds in reverse order. diff --git a/tests/e2e/ui/tests/integrationCritical/teamGlobalGuardrailKillSwitch.spec.ts b/tests/e2e/ui/tests/integrationCritical/teamGlobalGuardrailKillSwitch.spec.ts index ac48dd1a770..b71cd779c57 100644 --- a/tests/e2e/ui/tests/integrationCritical/teamGlobalGuardrailKillSwitch.spec.ts +++ b/tests/e2e/ui/tests/integrationCritical/teamGlobalGuardrailKillSwitch.spec.ts @@ -5,8 +5,9 @@ import { Page as PlaywrightPage, } from "@playwright/test"; import { randomUUID } from "node:crypto"; +import { masterKey } from "../../helpers/traffic"; -const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; +const master = masterKey(); const headers = { Authorization: `Bearer ${master}` }; async function createTeam(request: APIRequestContext): Promise { diff --git a/tests/e2e/ui/tests/integrationCritical/teamMetadataEmptyKey.spec.ts b/tests/e2e/ui/tests/integrationCritical/teamMetadataEmptyKey.spec.ts index d24ba963f05..1c3d466487d 100644 --- a/tests/e2e/ui/tests/integrationCritical/teamMetadataEmptyKey.spec.ts +++ b/tests/e2e/ui/tests/integrationCritical/teamMetadataEmptyKey.spec.ts @@ -5,8 +5,9 @@ import { Page as PlaywrightPage, } from "@playwright/test"; import { randomUUID } from "node:crypto"; +import { masterKey } from "../../helpers/traffic"; -const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; +const master = masterKey(); const headers = { Authorization: `Bearer ${master}` }; async function createTeamCarryingAnEmptyMetadataKey( diff --git a/tests/e2e/ui/tests/integrationCritical/toolPoliciesUserColumn.spec.ts b/tests/e2e/ui/tests/integrationCritical/toolPoliciesUserColumn.spec.ts index c65c8774d89..e04cf9b4d20 100644 --- a/tests/e2e/ui/tests/integrationCritical/toolPoliciesUserColumn.spec.ts +++ b/tests/e2e/ui/tests/integrationCritical/toolPoliciesUserColumn.spec.ts @@ -4,6 +4,7 @@ import { execFileSync } from "node:child_process"; import * as path from "node:path"; import { Page } from "../../fixtures/pages"; import { dismissFeedbackPopup, navigateToPage } from "../../helpers/navigation"; +import { masterKey } from "../../helpers/traffic"; /** * The Tool Policies table gets a User column: the owner of the key that discovered the tool, shown @@ -32,7 +33,7 @@ test("the Tool Policies page names the user behind the key that discovered a too page, request, }) => { - const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; + const master = masterKey(); const upstream = ( process.env.INTEGRATION_UPSTREAM_URL ?? "http://127.0.0.1:8190" ).replace(/\/+$/, ""); diff --git a/tests/e2e/ui/tests/modelHub/modelHub.spec.ts b/tests/e2e/ui/tests/modelHub/modelHub.spec.ts index 1fa3e4c530e..04b02d9ccc4 100644 --- a/tests/e2e/ui/tests/modelHub/modelHub.spec.ts +++ b/tests/e2e/ui/tests/modelHub/modelHub.spec.ts @@ -68,8 +68,7 @@ test.describe("Public model hub (/ui/model_hub_table)", () => { // The page expects the proxy key as the `key` query param. Use the master // key the e2e runner already exports — this matches what the AI Hub copy // button hands out. - const masterKey = process.env.LITELLM_MASTER_KEY || "sk-1234"; - await page.goto(`/ui/model_hub_table?key=${masterKey}`); + await page.goto(`/ui/model_hub_table?key=${masterKey()}`); // Dismiss the feedback popup before asserting on the tab, so a popup // race can't briefly mask the tab while we're evaluating visibility. diff --git a/tests/e2e/ui/tests/proxy-admin/teams.spec.ts b/tests/e2e/ui/tests/proxy-admin/teams.spec.ts index 303e4488e09..161492ef475 100644 --- a/tests/e2e/ui/tests/proxy-admin/teams.spec.ts +++ b/tests/e2e/ui/tests/proxy-admin/teams.spec.ts @@ -177,11 +177,11 @@ test.describe("Proxy Admin - Teams", () => { // Restore the seeded models via API in case a prior run (or a CI retry) // left this team mutated — the assertion below requires fake-anthropic-claude // to be present. - const masterKey = process.env.LITELLM_MASTER_KEY || "sk-1234"; + const key = masterKey(); const seededModels = ["fake-openai-gpt-4", "fake-anthropic-claude"]; const restore = async () => { const res = await request.post("/team/update", { - headers: { Authorization: `Bearer ${masterKey}` }, + headers: { Authorization: `Bearer ${key}` }, data: { team_id: E2E_TEAM_CRUD_ID, models: seededModels }, }); expect(res.ok(), `restore failed: ${res.status()} ${await res.text()}`).toBeTruthy(); diff --git a/tests/guardrails_tests/test_presidio_pii.py b/tests/guardrails_tests/test_presidio_pii.py index c1117c6c5b9..2960adfcbd3 100644 --- a/tests/guardrails_tests/test_presidio_pii.py +++ b/tests/guardrails_tests/test_presidio_pii.py @@ -232,7 +232,7 @@ async def test_presidio_pii_masking_input_a(): mock_testing=True, mock_redacted_text=input_a_anonymizer_results ) - _api_key = "sk-12345" + _api_key = "sk-98765" user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -264,7 +264,7 @@ async def test_presidio_pii_masking_input_b(): mock_testing=True, mock_redacted_text=input_b_anonymizer_results ) - _api_key = "sk-12345" + _api_key = "sk-98765" user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -296,7 +296,7 @@ async def test_presidio_pii_masking_logging_output_only_no_pre_api_hook(): mock_redacted_text=input_b_anonymizer_results, ) - _api_key = "sk-12345" + _api_key = "sk-98765" user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() diff --git a/tests/integration/oci_proxy_test_config.yaml b/tests/integration/oci_proxy_test_config.yaml index bccb58d27f3..95e74963cd2 100644 --- a/tests/integration/oci_proxy_test_config.yaml +++ b/tests/integration/oci_proxy_test_config.yaml @@ -18,7 +18,7 @@ model_list: mode: embedding general_settings: - master_key: sk-1234 + master_key: os.environ/LITELLM_MASTER_KEY litellm_settings: drop_params: True diff --git a/tests/integration/test_oci_proxy_integration.py b/tests/integration/test_oci_proxy_integration.py index f41e4826a04..06ed4486941 100644 --- a/tests/integration/test_oci_proxy_integration.py +++ b/tests/integration/test_oci_proxy_integration.py @@ -41,6 +41,7 @@ from typing import Iterator import httpx import pytest +from tests._master_key import MASTER_KEY # --------------------------------------------------------------------------- # Skip gate @@ -53,7 +54,6 @@ pytestmark = pytest.mark.skipif( CONFIG_PATH = Path(__file__).parent / "oci_proxy_test_config.yaml" -MASTER_KEY = "sk-1234" STARTUP_TIMEOUT_S = 90.0 REQUEST_TIMEOUT_S = 120.0 @@ -112,6 +112,7 @@ def _serve(config_path: str) -> Iterator[str]: """Boot the litellm proxy with the given config and yield its base URL.""" env = os.environ.copy() env.update(_oci_env_from_profile()) + env["LITELLM_MASTER_KEY"] = MASTER_KEY # Avoid pulling in DB-backed features for this lightweight smoke run. env.pop("DATABASE_URL", None) env["STORE_MODEL_IN_DB"] = "False" diff --git a/tests/litellm_utils_tests/test_cyberark.py b/tests/litellm_utils_tests/test_cyberark.py index 6d52cd9b079..fefc93af724 100644 --- a/tests/litellm_utils_tests/test_cyberark.py +++ b/tests/litellm_utils_tests/test_cyberark.py @@ -67,7 +67,7 @@ async def test_cyberark_write_secret_rejects_yaml_injection(): response = await cyberark_manager.async_write_secret( secret_name=malicious_secret_name, - secret_value="sk-1234", + secret_value="sk-9876", ) assert response["status"] == "error" @@ -186,7 +186,7 @@ async def test_cyberark_rotate_secret(): Test key rotation in CyberArk Conjur using mocked HTTP requests. This test simulates what happens when a virtual key is rotated: - 1. Write initial secret with alias (like sk-1234) + 1. Write initial secret with alias (like a proxy key) 2. Rotate to new value (like sk-12359) 3. Verify reading the secret returns the NEW value """ diff --git a/tests/litellm_utils_tests/test_health_check.py b/tests/litellm_utils_tests/test_health_check.py index cfdddd20263..499bcdd5910 100644 --- a/tests/litellm_utils_tests/test_health_check.py +++ b/tests/litellm_utils_tests/test_health_check.py @@ -581,7 +581,7 @@ async def test_health_check_bad_model(): { "model_name": "openai-gpt-4o", "litellm_params": { - "api_key": "sk-1234", + "api_key": "sk-9876", "api_base": "https://exampleopenaiendpoint-production.up.railway.app", "model": "openai/my-fake-openai-endpoint", "mock_timeout": True, diff --git a/tests/litellm_utils_tests/test_secret_manager.py b/tests/litellm_utils_tests/test_secret_manager.py index 4ba928dacd7..ae2b55c7b0d 100644 --- a/tests/litellm_utils_tests/test_secret_manager.py +++ b/tests/litellm_utils_tests/test_secret_manager.py @@ -76,7 +76,7 @@ def test_aws_secret_manager(): # cast json to dict secret_val = json.loads(secret_val) - assert secret_val["litellm_master_key"] == "sk-1234" + assert secret_val["litellm_master_key"] == os.environ["LITELLM_MASTER_KEY"] def redact_oidc_signature(secret_val): diff --git a/tests/litellm_utils_tests/test_utils.py b/tests/litellm_utils_tests/test_utils.py index 64402b5c016..401434c9d36 100644 --- a/tests/litellm_utils_tests/test_utils.py +++ b/tests/litellm_utils_tests/test_utils.py @@ -1436,7 +1436,7 @@ def test_get_valid_models_openai_proxy(monkeypatch): litellm._turn_on_debug() - monkeypatch.setenv("LITELLM_PROXY_API_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_PROXY_API_KEY", "sk-9876") monkeypatch.setenv("LITELLM_PROXY_API_BASE", "https://litellm-api.up.railway.app/") monkeypatch.delenv("FIREWORKS_AI_ACCOUNT_ID", None) monkeypatch.delenv("FIREWORKS_AI_API_KEY", None) @@ -1471,7 +1471,7 @@ def test_get_valid_models_fireworks_ai(monkeypatch): litellm._turn_on_debug() - monkeypatch.setenv("FIREWORKS_API_KEY", "sk-1234") + monkeypatch.setenv("FIREWORKS_API_KEY", "sk-9876") monkeypatch.setenv("FIREWORKS_ACCOUNT_ID", "1234") monkeypatch.setattr(litellm, "provider_list", ["fireworks_ai"]) @@ -1557,7 +1557,7 @@ def test_get_valid_models_default(monkeypatch): """ from litellm.utils import get_valid_models - monkeypatch.setenv("FIREWORKS_API_KEY", "sk-1234") + monkeypatch.setenv("FIREWORKS_API_KEY", "sk-9876") valid_models = get_valid_models() assert len(valid_models) > 0 diff --git a/tests/llm_translation/test_litellm_proxy_provider.py b/tests/llm_translation/test_litellm_proxy_provider.py index a7a2848a514..8a010467889 100644 --- a/tests/llm_translation/test_litellm_proxy_provider.py +++ b/tests/llm_translation/test_litellm_proxy_provider.py @@ -226,14 +226,14 @@ async def test_litellm_gateway_image_generation_direct(is_async): model="litellm_proxy/dall-e-3", prompt="A beautiful sunset over mountains", api_base="http://my-proxy", - api_key="sk-1234", + api_key="sk-9876", ) # Verify the AsyncOpenAI client constructor was called with correct parameters mock_async_constructor.assert_called_once() constructor_kwargs = mock_async_constructor.call_args.kwargs print("KWARGS to Async OpenAI constructor=", constructor_kwargs) - assert constructor_kwargs["api_key"] == "sk-1234" + assert constructor_kwargs["api_key"] == "sk-9876" assert constructor_kwargs["base_url"] == "http://my-proxy" # Verify the AsyncOpenAI client was called correctly @@ -253,13 +253,13 @@ async def test_litellm_gateway_image_generation_direct(is_async): model="litellm_proxy/dall-e-3", prompt="A beautiful sunset over mountains", api_base="http://my-proxy", - api_key="sk-1234", + api_key="sk-9876", ) # Verify the OpenAI client constructor was called with correct parameters mock_sync_constructor.assert_called_once() constructor_kwargs = mock_sync_constructor.call_args.kwargs - assert constructor_kwargs["api_key"] == "sk-1234" + assert constructor_kwargs["api_key"] == "sk-9876" assert constructor_kwargs["base_url"] == "http://my-proxy" # Verify the OpenAI client was called correctly @@ -309,7 +309,7 @@ async def test_litellm_gateway_from_sdk_image_edit(is_async): prompt="A test prompt", image=[image_file], api_base="http://my-proxy", - api_key="sk-1234", + api_key="sk-9876", ) mock_post.assert_awaited_once() else: @@ -318,13 +318,13 @@ async def test_litellm_gateway_from_sdk_image_edit(is_async): prompt="A test prompt", image=[image_file], api_base="http://my-proxy", - api_key="sk-1234", + api_key="sk-9876", ) mock_post.assert_called_once() called_kwargs = mock_post.call_args.kwargs assert called_kwargs["url"] == "http://my-proxy/images/edits" - assert called_kwargs["headers"]["Authorization"] == "Bearer sk-1234" + assert called_kwargs["headers"]["Authorization"] == "Bearer sk-9876" @pytest.mark.parametrize("is_async", [False, True]) diff --git a/tests/llm_translation/test_vcr_classification.py b/tests/llm_translation/test_vcr_classification.py index 781c37cf9c4..658d74fe13c 100644 --- a/tests/llm_translation/test_vcr_classification.py +++ b/tests/llm_translation/test_vcr_classification.py @@ -125,8 +125,8 @@ def test_should_extract_only_aws_access_key_from_sigv4_authorization(): def test_should_keep_bearer_authorization_unchanged(): """OpenAI ``Bearer `` headers are stable as-is — keep them.""" - out = _stable_key_value("Authorization", "Bearer sk-1234") - assert out == "Bearer sk-1234" + out = _stable_key_value("Authorization", "Bearer sk-9876") + assert out == "Bearer sk-9876" def test_should_produce_stable_fingerprint_across_sigv4_signatures(): diff --git a/tests/load_tests/memory_leak_utils.py b/tests/load_tests/memory_leak_utils.py index 8b9d24f020a..fae294e5a2c 100644 --- a/tests/load_tests/memory_leak_utils.py +++ b/tests/load_tests/memory_leak_utils.py @@ -36,7 +36,7 @@ from fastapi.responses import JSONResponse from litellm.router import Router # Test Configuration Constants -TEST_API_KEY = "sk-1234" +TEST_API_KEY = "sk-9876" TEST_MODEL_NAME = "gpt-3.5-turbo" # Timing Constants (seconds) diff --git a/tests/load_tests/test_granian_admission_saturation.py b/tests/load_tests/test_granian_admission_saturation.py index b42c06037c2..b55d75ee9f1 100644 --- a/tests/load_tests/test_granian_admission_saturation.py +++ b/tests/load_tests/test_granian_admission_saturation.py @@ -10,6 +10,8 @@ from typing import Final import httpx import pytest +from tests._master_key import MASTER_KEY + pytestmark = pytest.mark.skipif( os.environ.get("LITELLM_RUN_SATURATION_BENCHMARK") != "1", reason="set LITELLM_RUN_SATURATION_BENCHMARK=1 to run the saturation benchmark", @@ -32,6 +34,7 @@ async def test_granian_admission_control_saturation(tmp_path: Path) -> None: proxy_port: Final = _free_port() fake_script: Final = Path(__file__).parents[1] / "_fake_openai_endpoint_server.py" config_path: Final = tmp_path / "saturation_config.yaml" + proxy_env: Final = {**os.environ, "LITELLM_MASTER_KEY": MASTER_KEY} config_path.write_text( f"""model_list: - model_name: slow-endpoint @@ -39,7 +42,7 @@ async def test_granian_admission_control_saturation(tmp_path: Path) -> None: model: openai/slow-endpoint api_base: http://127.0.0.1:{fake_port}/v1 general_settings: - master_key: sk-saturation + master_key: os.environ/LITELLM_MASTER_KEY max_in_flight_requests_per_worker: 8 max_queued_requests_per_worker: 8 admission_queue_timeout_seconds: 0.5 @@ -64,6 +67,7 @@ general_settings: "--port", str(proxy_port), ], + env=proxy_env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) @@ -99,7 +103,7 @@ general_settings: start: Final = time.perf_counter() response = await client.post( "/chat/completions", - headers={"Authorization": "Bearer sk-saturation"}, + headers={"Authorization": f"Bearer {MASTER_KEY}"}, json={ "model": "slow-endpoint", "messages": [{"role": "user", "content": "hello"}], diff --git a/tests/local_testing/test_alangfuse.py b/tests/local_testing/test_alangfuse.py index bc388aebecf..c74f4010da0 100644 --- a/tests/local_testing/test_alangfuse.py +++ b/tests/local_testing/test_alangfuse.py @@ -730,7 +730,7 @@ def get_langfuse_prompt(name: str): async def test_make_request(): response = await litellm.acompletion( model="openai/llama3", - api_key="sk-1234", + api_key=os.environ["LITELLM_MASTER_KEY"], base_url="http://localhost:4000", messages=[{"role": "user", "content": "Hi 👋 - i'm claude"}], extra_body={ diff --git a/tests/local_testing/test_blocked_user_list.py b/tests/local_testing/test_blocked_user_list.py index 9bbe3fedf46..f7913c83662 100644 --- a/tests/local_testing/test_blocked_user_list.py +++ b/tests/local_testing/test_blocked_user_list.py @@ -59,6 +59,7 @@ from litellm.proxy._types import ( NewUserRequest, UpdateKeyRequest, ) +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -96,7 +97,7 @@ async def test_block_user_check(prisma_client): - Test to see if a call without that user is passes """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) litellm.blocked_user_list = ["user_id_1"] @@ -104,8 +105,8 @@ async def test_block_user_check(prisma_client): prisma_client=litellm.proxy.proxy_server.prisma_client ) - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -141,7 +142,7 @@ async def test_block_user_db_check(prisma_client): - Check returned value """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() _block_users = BlockUsers(user_ids=["user_id_1"]) result = await block_user(data=_block_users) diff --git a/tests/local_testing/test_config.py b/tests/local_testing/test_config.py index 6c3c0a093a7..be9eb0f2645 100644 --- a/tests/local_testing/test_config.py +++ b/tests/local_testing/test_config.py @@ -20,6 +20,7 @@ from litellm.proxy.common_utils.encrypt_decrypt_utils import encrypt_value from litellm.proxy.proxy_server import ProxyConfig from litellm.proxy.utils import DualCache, ProxyLogging from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo +from tests._master_key import MASTER_KEY class DBModel(BaseModel): @@ -48,7 +49,7 @@ async def test_delete_deployment(): ) encrypted_litellm_params = litellm_params.dict(exclude_none=True) - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "master_key", master_key) @@ -146,7 +147,7 @@ async def test_add_existing_deployment(): init_len_list = len(llm_router.model_list) print(f"llm_router: {llm_router}") - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "llm_router", llm_router) setattr(litellm.proxy.proxy_server, "master_key", master_key) pc = ProxyConfig() @@ -201,7 +202,7 @@ async def test_db_error_new_model_check(): init_len_list = len(llm_router.model_list) print(f"llm_router: {llm_router}") - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "llm_router", llm_router) setattr(litellm.proxy.proxy_server, "master_key", master_key) pc = ProxyConfig() @@ -322,7 +323,7 @@ async def test_add_and_delete_deployments(llm_router, model_list_flag_value): - when router is init and not empty """ - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "llm_router", llm_router) setattr(litellm.proxy.proxy_server, "master_key", master_key) pc = ProxyConfig() diff --git a/tests/local_testing/test_docker_no_network_on_deploy.py b/tests/local_testing/test_docker_no_network_on_deploy.py index 6d2a64a059f..8083eb912b4 100644 --- a/tests/local_testing/test_docker_no_network_on_deploy.py +++ b/tests/local_testing/test_docker_no_network_on_deploy.py @@ -20,6 +20,8 @@ import time import pytest +from tests._master_key import MASTER_KEY + def is_docker_available() -> bool: """Check if Docker is available and running.""" @@ -140,17 +142,17 @@ class TestDockerNoNetworkOnDeploy: network requests are required during startup. """ # Use a minimal config that doesn't require external services - minimal_config = """ + minimal_config = f""" model_list: - model_name: fake-model litellm_params: model: fake/fake-model general_settings: - master_key: sk-test-1234 + master_key: {MASTER_KEY} database_url: null -environment_variables: {} +environment_variables: {{}} """ # Create a temporary config file @@ -179,7 +181,7 @@ environment_variables: {} "-v", f"{config_path}:/app/config.yaml:ro", "-e", - "LITELLM_MASTER_KEY=sk-test-1234", + f"LITELLM_MASTER_KEY={MASTER_KEY}", "-e", "DATABASE_URL=", # Empty to disable DB "-e", @@ -350,7 +352,7 @@ def test_container_build_no_network_fetch(): This verifies that all dependencies are properly bundled and no runtime network calls are made during container initialization. - Note: Build itself may need network to resolve dependencies, but runtime should not. + Note: Build itself may need network to resolve dependencies, but runtime should not. """ # This is a simplified version - full test would need to: # 1. Build image with --network=none (requires pre-cached deps) diff --git a/tests/local_testing/test_llm_guard.py b/tests/local_testing/test_llm_guard.py index 9e70d48dbda..fc30f644028 100644 --- a/tests/local_testing/test_llm_guard.py +++ b/tests/local_testing/test_llm_guard.py @@ -40,8 +40,8 @@ async def test_llm_guard_valid_response(): mock_testing=True, mock_redacted_text=input_a_anonymizer_results ) - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -79,7 +79,7 @@ async def test_llm_guard_sanitizes_multimodal_and_input(): "scanners": {"Regex": 0.0}, }, ) - user_api_key_dict = UserAPIKeyAuth(api_key=hash_token("sk-12345")) + user_api_key_dict = UserAPIKeyAuth(api_key=hash_token("sk-98765")) image_part = {"type": "image_url", "image_url": {"url": "https://example.com/a.png"}} data = { @@ -121,8 +121,8 @@ async def test_llm_guard_error_raising(): mock_testing=True, mock_redacted_text=input_b_anonymizer_results ) - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -152,7 +152,7 @@ def test_llm_guard_key_specific_mode(): llm_guard = _ENTERPRISE_LLMGuard(mock_testing=True) - _api_key = "sk-12345" + _api_key = "sk-98765" # NOT ENABLED user_api_key_dict = UserAPIKeyAuth( api_key=_api_key, @@ -187,7 +187,7 @@ def test_llm_guard_request_specific_mode(): llm_guard = _ENTERPRISE_LLMGuard(mock_testing=True) - _api_key = "sk-12345" + _api_key = "sk-98765" # NOT ENABLED user_api_key_dict = UserAPIKeyAuth( api_key=_api_key, diff --git a/tests/local_testing/test_openai_moderations_hook.py b/tests/local_testing/test_openai_moderations_hook.py index 7ce4bc2e4bf..493a592b57e 100644 --- a/tests/local_testing/test_openai_moderations_hook.py +++ b/tests/local_testing/test_openai_moderations_hook.py @@ -33,8 +33,8 @@ async def test_openai_moderation_error_raising(monkeypatch): litellm.openai_moderations_model_name = "omni-moderation-latest" openai_mod = _ENTERPRISE_OpenAI_Moderation() - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() diff --git a/tests/local_testing/test_pass_through_endpoints.py b/tests/local_testing/test_pass_through_endpoints.py index 618354ca31e..41fcb3889b0 100644 --- a/tests/local_testing/test_pass_through_endpoints.py +++ b/tests/local_testing/test_pass_through_endpoints.py @@ -15,6 +15,7 @@ from unittest.mock import Mock import httpx from litellm.proxy.proxy_server import initialize_pass_through_endpoints +from tests._master_key import MASTER_KEY # Mock the async_client used in the pass_through_request function @@ -184,7 +185,7 @@ async def test_pass_through_endpoint_rpm_limit( proxy_logging_obj._init_litellm_callbacks() setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "FAKE-VAR") setattr(litellm.proxy.proxy_server, "proxy_logging_obj", proxy_logging_obj) @@ -288,7 +289,7 @@ async def test_pass_through_endpoint_sequential_rpm_limit( proxy_logging_obj._init_litellm_callbacks() setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "FAKE-VAR") setattr(litellm.proxy.proxy_server, "proxy_logging_obj", proxy_logging_obj) @@ -409,7 +410,7 @@ async def test_aaapass_through_endpoint_pass_through_keys_langfuse( proxy_logging_obj._init_litellm_callbacks() setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "FAKE-VAR") setattr(litellm.proxy.proxy_server, "proxy_logging_obj", proxy_logging_obj) diff --git a/tests/local_testing/test_prompt_injection_detection.py b/tests/local_testing/test_prompt_injection_detection.py index fa35dc5b060..0bbf562fe57 100644 --- a/tests/local_testing/test_prompt_injection_detection.py +++ b/tests/local_testing/test_prompt_injection_detection.py @@ -26,7 +26,7 @@ async def test_prompt_injection_attack_valid_attack(): """ prompt_injection_detection = _OPTIONAL_PromptInjectionDetection() - _api_key = "sk-12345" + _api_key = "sk-98765" user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() try: @@ -57,7 +57,7 @@ async def test_prompt_injection_attack_invalid_attack(): litellm.set_verbose = True prompt_injection_detection = _OPTIONAL_PromptInjectionDetection() - _api_key = "sk-12345" + _api_key = "sk-98765" user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() try: @@ -115,7 +115,7 @@ async def test_prompt_injection_llm_eval(): ), ) - _api_key = "sk-12345" + _api_key = "sk-98765" user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() try: diff --git a/tests/local_testing/test_secret_detect_hook.py b/tests/local_testing/test_secret_detect_hook.py index c560637b785..04278137d4e 100644 --- a/tests/local_testing/test_secret_detect_hook.py +++ b/tests/local_testing/test_secret_detect_hook.py @@ -43,8 +43,8 @@ async def test_basic_secret_detection_chat(): It should mask the following API_KEY = 'sk_1234567890abcdef' and OPENAI_API_KEY = 'sk_1234567890abcdef' """ secret_instance = _ENTERPRISE_SecretDetection() - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -111,8 +111,8 @@ async def test_basic_secret_detection_text_completion(): It should mask the following API_KEY = 'sk_1234567890abcdef' and OPENAI_API_KEY = 'sk_1234567890abcdef' """ secret_instance = _ENTERPRISE_SecretDetection() - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -149,8 +149,8 @@ async def test_basic_secret_detection_embeddings(): It should mask the following API_KEY = 'sk_1234567890abcdef' and OPENAI_API_KEY = 'sk_1234567890abcdef' """ secret_instance = _ENTERPRISE_SecretDetection() - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -187,8 +187,8 @@ async def test_basic_secret_detection_embeddings_list(): It should mask the following API_KEY = 'sk_1234567890abcdef' and OPENAI_API_KEY = 'sk_1234567890abcdef' """ secret_instance = _ENTERPRISE_SecretDetection() - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() @@ -242,7 +242,7 @@ router = Router( "litellm_params": { "model": "openai/fake", "api_base": FAKE_OPENAI_API_BASE, - "api_key": "sk-12345", + "api_key": "sk-98765", }, } ] @@ -281,15 +281,15 @@ async def test_chat_completion_request_with_redaction(): request._url = URL(url="/chat/completions") async def return_body(): - return b'{"model": "fake-model", "messages": [{"role": "user", "content": "Hello here is my OPENAI_API_KEY = sk-12345"}]}' + return b'{"model": "fake-model", "messages": [{"role": "user", "content": "Hello here is my OPENAI_API_KEY = sk-98765"}]}' request.body = return_body response = await chat_completion( request=request, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-12345", - token="hashed_sk-12345", + api_key="sk-98765", + token="hashed_sk-98765", ), fastapi_response=Response(), ) diff --git a/tests/local_testing/test_tpm_rpm_routing_v2.py b/tests/local_testing/test_tpm_rpm_routing_v2.py index 104afb0a14a..a4da78102de 100644 --- a/tests/local_testing/test_tpm_rpm_routing_v2.py +++ b/tests/local_testing/test_tpm_rpm_routing_v2.py @@ -519,7 +519,7 @@ def test_return_potential_deployments(): "model_name": "model-test", "litellm_params": { "rpm": 1, - "api_key": "sk-1234", + "api_key": "sk-9876", "model": "openai/gpt-3.5-turbo", "mock_response": "Hello, world!", }, @@ -532,7 +532,7 @@ def test_return_potential_deployments(): "model_name": "model-test", "litellm_params": { "rpm": 10, - "api_key": "sk-1234", + "api_key": "sk-9876", "model": "openai/o1-mini", "mock_response": "Hello, world, it's o1!", }, diff --git a/tests/local_testing/test_update_spend.py b/tests/local_testing/test_update_spend.py index b492a752c2c..96e75b6ffb7 100644 --- a/tests/local_testing/test_update_spend.py +++ b/tests/local_testing/test_update_spend.py @@ -58,6 +58,7 @@ from litellm.proxy._types import ( SpendUpdateQueueItem, Litellm_EntityType, ) +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -97,7 +98,7 @@ async def test_batch_update_spend(prisma_client): ) ) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() await update_spend( prisma_client=litellm.proxy.proxy_server.prisma_client, diff --git a/tests/mcp_tests/test_configs/test_config_mcp_e2e.yaml b/tests/mcp_tests/test_configs/test_config_mcp_e2e.yaml index 19fad3d1393..bdf6ad4e15a 100644 --- a/tests/mcp_tests/test_configs/test_config_mcp_e2e.yaml +++ b/tests/mcp_tests/test_configs/test_config_mcp_e2e.yaml @@ -1,5 +1,5 @@ general_settings: - master_key: sk-1234 + master_key: os.environ/LITELLM_MASTER_KEY litellm_settings: drop_params: true diff --git a/tests/mcp_tests/test_proxy_mcp_e2e.py b/tests/mcp_tests/test_proxy_mcp_e2e.py index 64e7483df6b..352f55eb983 100644 --- a/tests/mcp_tests/test_proxy_mcp_e2e.py +++ b/tests/mcp_tests/test_proxy_mcp_e2e.py @@ -27,6 +27,7 @@ from mcp.shared._httpx_utils import create_mcp_http_client from mcp.types import CallToolResult from starlette.requests import Request +from tests._master_key import MASTER_KEY from tests.integration._support.wire import Reply, Request as WireRequest, Wire, wire_server from litellm.integrations.custom_logger import CustomLogger @@ -47,7 +48,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[2] PROXY_START_TIMEOUT = 30 -PROXY_AUTHORIZATION_HEADER = "Bearer sk-1234" +PROXY_AUTHORIZATION_HEADER = f"Bearer {MASTER_KEY}" @pytest.mark.asyncio @@ -225,8 +226,7 @@ def _clear_proxy_database_env() -> typing.Iterator[None]: # The FastAPI lifespan event (proxy_startup_event) re-reads master_key from # the LITELLM_MASTER_KEY env var, overriding whatever initialize() set from # the config file. We must set it here so the lifespan doesn't reset it to None. - mp.setenv("LITELLM_MASTER_KEY", "sk-1234") - mp.setenv("LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY", "true") + mp.setenv("LITELLM_MASTER_KEY", MASTER_KEY) mp.setenv("LITELLM_ENABLE_MCP_STDIO", "true") try: yield @@ -396,7 +396,10 @@ from mcp.client.streamable_http import streamablehttp_client from langchain_mcp_adapters.tools import load_mcp_tools async def main(): - async with streamablehttp_client(sys.argv[1] + '/mcp', headers={'Authorization': 'Bearer sk-1234'}) as (read, write, _): + async with streamablehttp_client( + sys.argv[1] + "/mcp", + headers={"Authorization": "Bearer " + os.environ["LITELLM_MASTER_KEY"]}, + ) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() tools = await load_mcp_tools(session) @@ -703,7 +706,7 @@ class TestProxyMcpSchemaDiscoveryMode: async def authorize_proxy_key(request: Request, api_key: str) -> UserAPIKeyAuth: permissions = { "sk-schema": LiteLLM_ObjectPermissionTable(object_permission_id="schema", mcp_servers=["schema"]), - "sk-1234": LiteLLM_ObjectPermissionTable(object_permission_id="open", mcp_servers=["math_stdio"]), + "sk-9876": LiteLLM_ObjectPermissionTable(object_permission_id="open", mcp_servers=["math_stdio"]), "sk-restricted": LiteLLM_ObjectPermissionTable( object_permission_id="restricted", mcp_servers=["math_restricted"] ), @@ -743,7 +746,7 @@ proxy_call_recorder = ProxyCallRecorder() @asynccontextmanager -async def _scoped_session(url: str, key: str = "sk-1234", **headers: str) -> typing.AsyncIterator[ClientSession]: +async def _scoped_session(url: str, key: str = "sk-9876", **headers: str) -> typing.AsyncIterator[ClientSession]: async with asyncio.timeout(30): async with _proxy_session(url, Authorization=f"Bearer {key}", **headers) as (read, write): async with ClientSession(read, write) as session: diff --git a/tests/multi_instance_e2e_tests/test_update_team_e2e.py b/tests/multi_instance_e2e_tests/test_update_team_e2e.py index ce88e976ce0..042b87193ae 100644 --- a/tests/multi_instance_e2e_tests/test_update_team_e2e.py +++ b/tests/multi_instance_e2e_tests/test_update_team_e2e.py @@ -1,3 +1,4 @@ +import os import pytest import asyncio import aiohttp @@ -16,7 +17,7 @@ async def generate_team_key( ): """Helper function to generate a key for a specific team""" url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data: dict[str, Any] = {"team_id": team_id} if max_budget is not None: data["max_budget"] = max_budget @@ -27,7 +28,7 @@ async def generate_team_key( async def update_team_block_status(session, team_id: str, blocked: bool, port: int): """Helper to update a team's 'blocked' status on a given instance port.""" url = f"http://0.0.0.0:{port}/team/update" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"team_id": team_id, "blocked": blocked} async with session.post(url, headers=headers, json=data) as response: return await response.json() @@ -36,7 +37,7 @@ async def update_team_block_status(session, team_id: str, blocked: bool, port: i async def get_team_info(session, team_id: str, port: int): """Helper to retrieve team info from a specific instance port.""" url = f"http://0.0.0.0:{port}/team/info" - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"} async with session.get( url, headers=headers, params={"team_id": team_id} ) as response: @@ -87,7 +88,7 @@ async def test_team_blocking_behavior_multi_instance(): """ async with aiohttp.ClientSession() as session: headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } diff --git a/tests/openai_endpoints_tests/test_e2e_openai_responses_api.py b/tests/openai_endpoints_tests/test_e2e_openai_responses_api.py index 566af351a98..260656600ec 100644 --- a/tests/openai_endpoints_tests/test_e2e_openai_responses_api.py +++ b/tests/openai_endpoints_tests/test_e2e_openai_responses_api.py @@ -1,3 +1,4 @@ +import os import time from collections.abc import Iterator from typing import Final @@ -14,7 +15,7 @@ def generate_key(): """Generate a key for testing""" url = "http://0.0.0.0:4000/key/generate" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } data = {} diff --git a/tests/openai_endpoints_tests/test_openai_batches_endpoint.py b/tests/openai_endpoints_tests/test_openai_batches_endpoint.py index 38c7b6e9138..ec265167271 100644 --- a/tests/openai_endpoints_tests/test_openai_batches_endpoint.py +++ b/tests/openai_endpoints_tests/test_openai_batches_endpoint.py @@ -1,5 +1,6 @@ # What this tests ? ## Tests /batches endpoints +import os import pytest import asyncio import aiohttp, openai @@ -12,7 +13,7 @@ from unittest.mock import patch, MagicMock, AsyncMock BASE_URL = "http://localhost:4000" # Replace with your actual base URL -API_KEY = "sk-1234" # Replace with your actual API key +API_KEY = os.environ["LITELLM_MASTER_KEY"] # Replace with your actual API key client = OpenAI(base_url=BASE_URL, api_key=API_KEY) diff --git a/tests/openai_endpoints_tests/test_openai_files_endpoints.py b/tests/openai_endpoints_tests/test_openai_files_endpoints.py index 6be692b278c..9398a0d1c53 100644 --- a/tests/openai_endpoints_tests/test_openai_files_endpoints.py +++ b/tests/openai_endpoints_tests/test_openai_files_endpoints.py @@ -1,3 +1,4 @@ +import os # What this tests ? ## Tests /chat/completions by generating a key and then making a chat completions request import pytest @@ -8,7 +9,7 @@ from typing import Optional, List, Union BASE_URL = "http://localhost:4000" # Replace with your actual base URL -API_KEY = "sk-1234" # Replace with your actual API key +API_KEY = os.environ["LITELLM_MASTER_KEY"] # Replace with your actual API key @pytest.mark.asyncio diff --git a/tests/openai_endpoints_tests/test_openai_fine_tuning.py b/tests/openai_endpoints_tests/test_openai_fine_tuning.py index 8d46692a808..0c9ea5af848 100644 --- a/tests/openai_endpoints_tests/test_openai_fine_tuning.py +++ b/tests/openai_endpoints_tests/test_openai_fine_tuning.py @@ -11,7 +11,7 @@ async def test_openai_fine_tuning(): [PROD Test] e2e tests for /fine_tuning/jobs endpoints """ try: - client = AsyncOpenAI(api_key="sk-1234", base_url="http://0.0.0.0:4000") + client = AsyncOpenAI(api_key=os.environ["LITELLM_MASTER_KEY"], base_url="http://0.0.0.0:4000") file_name = "openai_fine_tuning.jsonl" _current_dir = os.path.dirname(os.path.abspath(__file__)) diff --git a/tests/otel_tests/test_e2e_budgeting.py b/tests/otel_tests/test_e2e_budgeting.py index 5b673d9829f..f180403e115 100644 --- a/tests/otel_tests/test_e2e_budgeting.py +++ b/tests/otel_tests/test_e2e_budgeting.py @@ -1,3 +1,4 @@ +import os import asyncio import json import secrets @@ -10,7 +11,7 @@ import pytest from httpx import AsyncClient PROXY_BASE = "http://0.0.0.0:4000" -MASTER_HEADERS = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} +MASTER_HEADERS = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} CLI_SSO_MODEL = "fake-openai-endpoint" @@ -59,7 +60,7 @@ async def generate_key( max_budget=None, ): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "max_budget": max_budget, } @@ -175,7 +176,7 @@ async def test_key_limit_modifications(field): # Create initial key client = AsyncClient(base_url="http://0.0.0.0:4000") key_data = {"max_budget": None, "rpm_limit": None, "tpm_limit": None} - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"} response = await client.post("/key/generate", json=key_data, headers=headers) assert response.status_code == 200 generate_key_response = response.json() @@ -210,7 +211,7 @@ async def test_team_limit_modifications(field): # Create initial team client = AsyncClient(base_url="http://0.0.0.0:4000") team_data = {"max_budget": None, "rpm_limit": None, "tpm_limit": None} - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"} response = await client.post("/team/new", json=team_data, headers=headers) print("response: ", json.dumps(response.json(), indent=4)) assert response.status_code == 200 @@ -240,7 +241,7 @@ async def generate_team_key( ): """Helper function to generate a key for a specific team""" url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data: dict[str, Any] = {"team_id": team_id} if max_budget is not None: data["max_budget"] = max_budget diff --git a/tests/otel_tests/test_e2e_model_access.py b/tests/otel_tests/test_e2e_model_access.py index 6017a820299..bdd6b597f68 100644 --- a/tests/otel_tests/test_e2e_model_access.py +++ b/tests/otel_tests/test_e2e_model_access.py @@ -1,3 +1,4 @@ +import os import pytest import asyncio import aiohttp @@ -18,7 +19,7 @@ async def generate_key( ): """Helper function to generate a key with specific model access controls""" url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data: dict = {"metadata": dict(_ALLOW_CLIENT_MOCK_METADATA)} if models is not None: data["models"] = models @@ -31,7 +32,7 @@ async def generate_key( async def generate_team(session, models: Optional[List[str]] = None): """Helper function to generate a team with specific model access""" url = "http://0.0.0.0:4000/team/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data: dict = {"metadata": dict(_ALLOW_CLIENT_MOCK_METADATA)} if models is not None: data["models"] = models @@ -114,7 +115,7 @@ async def test_model_access_update(): 4. Verify new access patterns """ client = AsyncClient(base_url="http://0.0.0.0:4000") - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"} # Create initial key with restricted access response = await client.post( @@ -183,7 +184,7 @@ async def test_team_model_access_patterns(team_models, test_model, expect_succes 4. Verify access is granted/denied as expected """ client = AsyncClient(base_url="http://0.0.0.0:4000") - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"} async with aiohttp.ClientSession() as session: try: @@ -221,7 +222,7 @@ async def test_team_model_access_update(): 4. Verify new access patterns """ client = AsyncClient(base_url="http://0.0.0.0:4000") - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"} # Create initial team with restricted access response = await client.post( diff --git a/tests/otel_tests/test_guardrails.py b/tests/otel_tests/test_guardrails.py index 758b244d259..3aa6b8cb2e7 100644 --- a/tests/otel_tests/test_guardrails.py +++ b/tests/otel_tests/test_guardrails.py @@ -1,3 +1,4 @@ +import os import pytest import asyncio import aiohttp, openai @@ -51,7 +52,7 @@ async def generate_key( session, guardrails: Optional[List] = None, team_id: Optional[str] = None ): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {} if guardrails: data["guardrails"] = guardrails @@ -81,7 +82,7 @@ async def test_llm_guard_triggered_safe_request(): async with aiohttp.ClientSession() as session: response, headers = await chat_completion( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], model="fake-openai-endpoint", messages=[{"role": "user", "content": f"Hello what's the weather"}], guardrails=[ @@ -112,7 +113,7 @@ async def test_llm_guard_triggered(): with pytest.raises(Exception, match="Aporia detected and blocked PII") as exc_info: response, headers = await chat_completion( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], model="fake-openai-endpoint", messages=[ {"role": "user", "content": f"Hello my name is ishaan@berri.ai"} @@ -136,7 +137,7 @@ async def test_no_llm_guard_triggered(): async with aiohttp.ClientSession() as session: response, headers = await chat_completion( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], model="fake-openai-endpoint", messages=[{"role": "user", "content": f"Hello what's the weather"}], guardrails=[], @@ -205,7 +206,7 @@ async def test_bedrock_guardrail_triggered(): with pytest.raises(Exception, match="Violated guardrail policy") as exc_info: response, headers = await chat_completion( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], model="fake-openai-endpoint", messages=[{"role": "user", "content": "Hello do you like coffee?"}], guardrails=["bedrock-pre-guard"], @@ -225,7 +226,7 @@ async def test_custom_guardrail_during_call_triggered(): with pytest.raises(Exception, match="Guardrail failed words - `litellm` detected") as exc_info: response, headers = await chat_completion( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], model="fake-openai-endpoint", messages=[{"role": "user", "content": f"Hello do you like litellm?"}], guardrails=["custom-during-guard"], @@ -237,7 +238,7 @@ async def test_custom_guardrail_during_call_triggered(): async def create_team(session, guardrails: Optional[List] = None): url = "http://0.0.0.0:4000/team/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"guardrails": guardrails} print("request data=", data) @@ -317,7 +318,7 @@ async def test_guardrails_with_team_controls(): async def get_guardrail_lb_counts(session): """Get the current guardrail load balancing call counts from the proxy.""" url = "http://0.0.0.0:4000/guardrail/lb/counts" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} async with session.get(url, headers=headers) as response: if response.status == 200: @@ -341,7 +342,7 @@ async def test_guardrail_load_balancing(): for i in range(num_requests): response, headers = await chat_completion( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], model="fake-openai-endpoint", messages=[{"role": "user", "content": f"Hello request {i}"}], guardrails=["lb-test-guard"], diff --git a/tests/otel_tests/test_key_logging_callbacks.py b/tests/otel_tests/test_key_logging_callbacks.py index f3dbc10adb6..1736831eb69 100644 --- a/tests/otel_tests/test_key_logging_callbacks.py +++ b/tests/otel_tests/test_key_logging_callbacks.py @@ -3,6 +3,7 @@ Tests for Key based logging callbacks """ +import os import httpx import pytest @@ -16,7 +17,7 @@ async def test_key_logging_callbacks(): # Generate a key with logging callback generate_url = "http://0.0.0.0:4000/key/generate" generate_headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } generate_payload = { diff --git a/tests/otel_tests/test_model_info.py b/tests/otel_tests/test_model_info.py index 6136fe0e850..66a81eeee51 100644 --- a/tests/otel_tests/test_model_info.py +++ b/tests/otel_tests/test_model_info.py @@ -2,6 +2,7 @@ /model/info test """ +import os import httpx import pytest @@ -11,7 +12,7 @@ async def test_custom_model_supports_vision(): async with httpx.AsyncClient() as client: response = await client.get( "http://localhost:4000/model/info", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"}, ) assert response.status_code == 200 diff --git a/tests/otel_tests/test_moderations.py b/tests/otel_tests/test_moderations.py index 822e2558889..a9c73c93500 100644 --- a/tests/otel_tests/test_moderations.py +++ b/tests/otel_tests/test_moderations.py @@ -1,3 +1,4 @@ +import os import pytest import asyncio import aiohttp, openai @@ -40,7 +41,7 @@ async def test_basic_moderations_on_proxy_no_model(): try: response = await make_moderations_curl_request( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], request_data, ) print("response=", response) @@ -63,7 +64,7 @@ async def test_basic_moderations_on_proxy_with_model(): try: response = await make_moderations_curl_request( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], request_data, ) print("response=", response) diff --git a/tests/otel_tests/test_prometheus.py b/tests/otel_tests/test_prometheus.py index 84d5f48a706..7224334105d 100644 --- a/tests/otel_tests/test_prometheus.py +++ b/tests/otel_tests/test_prometheus.py @@ -2,6 +2,7 @@ Unit tests for prometheus metrics """ +import os import pytest import aiohttp import asyncio @@ -88,7 +89,7 @@ async def test_proxy_failure_metrics(): async with aiohttp.ClientSession() as session: # Make a bad chat completion call status, response_text = await make_bad_chat_completion_request( - session, "sk-1234" + session, os.environ["LITELLM_MASTER_KEY"] ) # Check if the request failed as expected @@ -180,7 +181,7 @@ async def test_proxy_success_metrics(): async with aiohttp.ClientSession() as session: # Make a good chat completion call status, response_text = await make_good_chat_completion_request( - session, "sk-1234" + session, os.environ["LITELLM_MASTER_KEY"] ) # Check if the request succeeded as expected @@ -293,7 +294,7 @@ async def test_proxy_fallback_metrics(): async with aiohttp.ClientSession() as session: # Make a good chat completion call - await make_chat_completion_request_with_fallback(session, "sk-1234") + await make_chat_completion_request_with_fallback(session, os.environ["LITELLM_MASTER_KEY"]) # Get metrics async with session.get("http://0.0.0.0:4000/metrics") as response: @@ -354,7 +355,7 @@ async def create_test_team( """Create a new team and return the team_id""" url = "http://0.0.0.0:4000/team/new" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } @@ -372,7 +373,7 @@ async def create_test_user( """Create a new user and return the user info""" url = "http://0.0.0.0:4000/user/new" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } @@ -419,7 +420,7 @@ async def create_test_key(session: aiohttp.ClientSession, team_id: str) -> str: """Generate a new key for the team and return it""" url = "http://0.0.0.0:4000/key/generate" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } data = { @@ -438,7 +439,7 @@ async def get_team_info(session: aiohttp.ClientSession, team_id: str) -> Dict[st """Fetch team info and return the response""" url = f"http://0.0.0.0:4000/team/info?team_id={team_id}" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", } async with session.get(url, headers=headers) as response: @@ -527,7 +528,7 @@ async def create_test_key_with_budget( """Generate a new key with budget constraints and return it""" url = "http://0.0.0.0:4000/key/generate" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", } print("budget_data", budget_data) @@ -562,7 +563,7 @@ async def get_user_info(session: aiohttp.ClientSession, user_id: str) -> Dict[st encoded_user_id = quote(user_id, safe="") url = f"http://0.0.0.0:4000/user/info?user_id={encoded_user_id}" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", } async with session.get(url, headers=headers) as response: diff --git a/tests/otel_tests/test_rerank.py b/tests/otel_tests/test_rerank.py index f04d82442a3..15031ef0532 100644 --- a/tests/otel_tests/test_rerank.py +++ b/tests/otel_tests/test_rerank.py @@ -1,3 +1,4 @@ +import os import pytest import asyncio import aiohttp, openai @@ -55,7 +56,7 @@ async def test_basic_rerank_on_proxy(): try: response = await make_rerank_curl_request( session, - "sk-1234", + os.environ["LITELLM_MASTER_KEY"], query="What is the capital of the United States?", documents=docs, ) diff --git a/tests/otel_tests/test_team_tag_routing.py b/tests/otel_tests/test_team_tag_routing.py index 82294bee664..b818aa0cea4 100644 --- a/tests/otel_tests/test_team_tag_routing.py +++ b/tests/otel_tests/test_team_tag_routing.py @@ -1,3 +1,4 @@ +import os # What this tests ? ## Set tags on a team and then make a request to /chat/completions import pytest @@ -7,7 +8,7 @@ from openai import OpenAI, AsyncOpenAI from typing import Optional, List, Union from litellm._uuid import uuid -LITELLM_MASTER_KEY = "sk-1234" +LITELLM_MASTER_KEY = os.environ["LITELLM_MASTER_KEY"] async def chat_completion( diff --git a/tests/pass_through_tests/test_anthropic_passthrough.py b/tests/pass_through_tests/test_anthropic_passthrough.py index 0452b171f9e..5d6ddb1fbd0 100644 --- a/tests/pass_through_tests/test_anthropic_passthrough.py +++ b/tests/pass_through_tests/test_anthropic_passthrough.py @@ -2,6 +2,7 @@ This test ensures that the proxy can passthrough anthropic requests """ +import os import pytest import anthropic import aiohttp @@ -15,7 +16,7 @@ async def test_anthropic_basic_completion_with_headers(): print("making basic completion request to anthropic passthrough with aiohttp") headers = { - "Authorization": f"Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", "Anthropic-Version": "2023-06-01", } @@ -65,7 +66,7 @@ async def test_anthropic_basic_completion_with_headers(): async with session.get( f"http://0.0.0.0:4000/spend/logs?request_id={anthropic_message_id}", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"}, ) as spend_response: print("text spend response") print(f"Spend response: {spend_response}") @@ -155,7 +156,7 @@ async def test_anthropic_streaming_with_headers(): print("making streaming request to anthropic passthrough with aiohttp") headers = { - "Authorization": f"Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", "Anthropic-Version": "2023-06-01", } @@ -236,7 +237,7 @@ async def test_anthropic_streaming_with_headers(): async with session.get( f"http://0.0.0.0:4000/spend/logs?request_id={anthropic_message_id}", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"}, ) as spend_response: spend_data = await spend_response.json() print(f"Spend data: {spend_data}") @@ -330,7 +331,7 @@ async def test_anthropic_messages_streaming_cost_injection(): print("Testing cost injection in Anthropic Messages API streaming response") headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", "anthropic-version": "2023-06-01", } @@ -404,7 +405,7 @@ async def test_anthropic_messages_openai_model_streaming_cost_injection(): print("Testing cost injection in Anthropic Messages API with OpenAI model") headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", "anthropic-version": "2023-06-01", } diff --git a/tests/pass_through_tests/test_anthropic_passthrough_basic.py b/tests/pass_through_tests/test_anthropic_passthrough_basic.py index 21e53994dcc..c7e9fea867c 100644 --- a/tests/pass_through_tests/test_anthropic_passthrough_basic.py +++ b/tests/pass_through_tests/test_anthropic_passthrough_basic.py @@ -1,3 +1,4 @@ +import os from base_anthropic_messages_test import BaseAnthropicMessagesTest import anthropic @@ -7,7 +8,7 @@ class TestAnthropicPassthroughBasic(BaseAnthropicMessagesTest): def get_client(self): return anthropic.Anthropic( base_url="http://0.0.0.0:4000/anthropic", - api_key="sk-1234", + api_key=os.environ["LITELLM_MASTER_KEY"], ) @@ -15,7 +16,7 @@ class TestAnthropicMessagesEndpoint(BaseAnthropicMessagesTest): def get_client(self): return anthropic.Anthropic( base_url="http://0.0.0.0:4000", - api_key="sk-1234", + api_key=os.environ["LITELLM_MASTER_KEY"], ) def test_anthropic_messages_to_wildcard_model(self): diff --git a/tests/pass_through_tests/test_anthropic_passthrough_python_sdkpy b/tests/pass_through_tests/test_anthropic_passthrough_python_sdkpy index e611a2d86a6..3321735e63c 100644 --- a/tests/pass_through_tests/test_anthropic_passthrough_python_sdkpy +++ b/tests/pass_through_tests/test_anthropic_passthrough_python_sdkpy @@ -4,9 +4,10 @@ This test ensures that the proxy can passthrough anthropic requests import pytest import anthropic +import os client = anthropic.Anthropic( - base_url="http://0.0.0.0:4000/anthropic", api_key="sk-1234" + base_url="http://0.0.0.0:4000/anthropic", api_key=os.environ["LITELLM_MASTER_KEY"] ) diff --git a/tests/pass_through_tests/test_assembly_ai.py b/tests/pass_through_tests/test_assembly_ai.py index 31bdf24009a..09999bc2bed 100644 --- a/tests/pass_through_tests/test_assembly_ai.py +++ b/tests/pass_through_tests/test_assembly_ai.py @@ -2,6 +2,7 @@ This test ensures that the proxy can passthrough requests to assemblyai """ +import os import time import pytest @@ -9,7 +10,7 @@ import httpx import aiohttp import asyncio -TEST_MASTER_KEY = "sk-1234" +TEST_MASTER_KEY = os.environ["LITELLM_MASTER_KEY"] TEST_BASE_URL = "http://0.0.0.0:4000/assemblyai" diff --git a/tests/pass_through_tests/test_gemini.js b/tests/pass_through_tests/test_gemini.js index 2b7d6c5c61f..ae1eb0c5cdb 100644 --- a/tests/pass_through_tests/test_gemini.js +++ b/tests/pass_through_tests/test_gemini.js @@ -1,6 +1,6 @@ // const { GoogleGenerativeAI } = require("@google/generative-ai"); -// const genAI = new GoogleGenerativeAI("sk-1234"); +// const genAI = new GoogleGenerativeAI(process.env.LITELLM_MASTER_KEY); // const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" }); // const prompt = "Explain how AI works in 2 pages"; diff --git a/tests/pass_through_tests/test_gemini_with_spend.test.js b/tests/pass_through_tests/test_gemini_with_spend.test.js index b9a25d3a3ed..f59d575c033 100644 --- a/tests/pass_through_tests/test_gemini_with_spend.test.js +++ b/tests/pass_through_tests/test_gemini_with_spend.test.js @@ -2,6 +2,9 @@ const { GoogleGenerativeAI } = require("@google/generative-ai"); const fs = require('fs'); const path = require('path'); +const masterKey = process.env.LITELLM_MASTER_KEY; +if (!masterKey) throw new Error("LITELLM_MASTER_KEY must be set"); + // Import fetch if the SDK uses it const originalFetch = global.fetch || require('node-fetch'); @@ -22,7 +25,7 @@ jest.retryTimes(3); describe('Gemini AI Tests', () => { test('should successfully generate non-streaming content with tags', async () => { - const genAI = new GoogleGenerativeAI("sk-1234"); // litellm proxy API key + const genAI = new GoogleGenerativeAI(masterKey); const requestOptions = { baseUrl: 'http://127.0.0.1:4000/gemini', @@ -50,7 +53,7 @@ describe('Gemini AI Tests', () => { await new Promise(resolve => setTimeout(resolve, 10000)); const spendResponse = await fetch( `http://127.0.0.1:4000/spend/logs?request_id=${callId}`, - { headers: { 'Authorization': 'Bearer sk-1234' } } + { headers: { 'Authorization': `Bearer ${masterKey}` } } ); spendData = await spendResponse.json(); console.log(`spendData (attempt ${attempt + 1}):`, spendData); @@ -73,7 +76,7 @@ describe('Gemini AI Tests', () => { }, 90000); test('should successfully generate streaming content with tags', async () => { - const genAI = new GoogleGenerativeAI("sk-1234"); // litellm proxy API key + const genAI = new GoogleGenerativeAI(masterKey); const requestOptions = { baseUrl: 'http://127.0.0.1:4000/gemini', @@ -110,7 +113,7 @@ describe('Gemini AI Tests', () => { await new Promise(resolve => setTimeout(resolve, 10000)); const spendResponse = await fetch( `http://127.0.0.1:4000/spend/logs?request_id=${callId}`, - { headers: { 'Authorization': 'Bearer sk-1234' } } + { headers: { 'Authorization': `Bearer ${masterKey}` } } ); spendData = await spendResponse.json(); console.log(`spendData (attempt ${attempt + 1}):`, spendData); diff --git a/tests/pass_through_tests/test_local_gemini.js b/tests/pass_through_tests/test_local_gemini.js index dc033a51f18..157121e6caf 100644 --- a/tests/pass_through_tests/test_local_gemini.js +++ b/tests/pass_through_tests/test_local_gemini.js @@ -1,5 +1,8 @@ const { GoogleGenerativeAI, ModelParams, RequestOptions } = require("@google/generative-ai"); +const masterKey = process.env.LITELLM_MASTER_KEY; +if (!masterKey) throw new Error("LITELLM_MASTER_KEY must be set"); + const modelParams = { model: 'gemini-3.1-flash-lite', }; @@ -11,7 +14,7 @@ const requestOptions = { } }; -const genAI = new GoogleGenerativeAI("sk-1234"); // litellm proxy API key +const genAI = new GoogleGenerativeAI(masterKey); const model = genAI.getGenerativeModel(modelParams, requestOptions); const testPrompt = "Explain how AI works"; diff --git a/tests/pass_through_tests/test_local_vertex.js b/tests/pass_through_tests/test_local_vertex.js index 7cfe31db95b..37f8245a638 100644 --- a/tests/pass_through_tests/test_local_vertex.js +++ b/tests/pass_through_tests/test_local_vertex.js @@ -1,5 +1,8 @@ const { VertexAI, RequestOptions } = require('@google-cloud/vertexai'); +const masterKey = process.env.LITELLM_MASTER_KEY; +if (!masterKey) throw new Error("LITELLM_MASTER_KEY must be set"); + const vertexAI = new VertexAI({ @@ -10,7 +13,7 @@ const vertexAI = new VertexAI({ // Create customHeaders using Headers const customHeaders = new Headers({ - "X-Litellm-Api-Key": "sk-1234", + "X-Litellm-Api-Key": masterKey, tags: "vertexjs,test-2" }); diff --git a/tests/pass_through_tests/test_openai_assistants_passthrough.py b/tests/pass_through_tests/test_openai_assistants_passthrough.py index 9afd8b23b2f..4da84ce5ca3 100644 --- a/tests/pass_through_tests/test_openai_assistants_passthrough.py +++ b/tests/pass_through_tests/test_openai_assistants_passthrough.py @@ -1,8 +1,9 @@ +import os import openai import tempfile -client = openai.OpenAI(base_url="http://0.0.0.0:4000/openai", api_key="sk-1234") +client = openai.OpenAI(base_url="http://0.0.0.0:4000/openai", api_key=os.environ["LITELLM_MASTER_KEY"]) def test_pass_through_file_operations(): diff --git a/tests/pass_through_tests/test_vertex.test.js b/tests/pass_through_tests/test_vertex.test.js index 3663d35d192..ec83ccdcbc0 100644 --- a/tests/pass_through_tests/test_vertex.test.js +++ b/tests/pass_through_tests/test_vertex.test.js @@ -10,6 +10,9 @@ const originalFetch = global.fetch || require('node-fetch'); const { runVertexRequestOrSkip } = require('./vertex_test_helpers'); +const masterKey = process.env.LITELLM_MASTER_KEY; +if (!masterKey) throw new Error("LITELLM_MASTER_KEY must be set"); + // Monkey-patch the fetch used internally global.fetch = async function patchedFetch(url, options) { // Modify the URL to use HTTP instead of HTTPS @@ -75,7 +78,7 @@ describe('Vertex AI Tests', () => { }); const customHeaders = new Headers({ - "x-litellm-api-key": "sk-1234" + "x-litellm-api-key": masterKey }); const requestOptions = { @@ -121,7 +124,7 @@ describe('Vertex AI Tests', () => { location: 'global', apiEndpoint: "localhost:4000/vertex-ai" }); - const customHeaders = new Headers({"x-litellm-api-key": "sk-1234"}); + const customHeaders = new Headers({"x-litellm-api-key": masterKey}); const requestOptions = {customHeaders: customHeaders}; const generativeModel = vertexAI.getGenerativeModel( {model: 'gemini-3.1-flash-lite'}, diff --git a/tests/pass_through_tests/test_vertex_ai.py b/tests/pass_through_tests/test_vertex_ai.py index 35cb5f49c56..c1de9ae777d 100644 --- a/tests/pass_through_tests/test_vertex_ai.py +++ b/tests/pass_through_tests/test_vertex_ai.py @@ -72,7 +72,7 @@ def get_tracked_spend() -> float: treats an unreachable endpoint as "nothing recorded yet" (0.0). """ url = f"{LITE_LLM_ENDPOINT}/global/spend/logs?api_key={SPEND_LOG_API_KEY}" - response = requests.get(url, headers={"Authorization": "Bearer sk-1234"}) + response = requests.get(url, headers={"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"}) if response.status_code != 200: print(f"global spend logs endpoint returned {response.status_code}: {response.text}") return 0.0 @@ -104,7 +104,7 @@ def _vertex_access_token() -> str: def _spend_log_for_request(call_id: str) -> dict | None: response = requests.get( f"{LITE_LLM_ENDPOINT}/spend/logs?request_id={call_id}", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}"}, timeout=30, ) if response.status_code != 200: diff --git a/tests/pass_through_tests/test_vertex_with_spend.test.js b/tests/pass_through_tests/test_vertex_with_spend.test.js index 5914908e66a..57d697185ea 100644 --- a/tests/pass_through_tests/test_vertex_with_spend.test.js +++ b/tests/pass_through_tests/test_vertex_with_spend.test.js @@ -12,6 +12,9 @@ let lastCallId; const { runVertexRequestOrSkip } = require('./vertex_test_helpers'); +const masterKey = process.env.LITELLM_MASTER_KEY; +if (!masterKey) throw new Error("LITELLM_MASTER_KEY must be set"); + // Monkey-patch the fetch used internally global.fetch = async function patchedFetch(url, options) { // Modify the URL to use HTTP instead of HTTPS @@ -78,7 +81,7 @@ describe('Vertex AI Tests', () => { }); const customHeaders = new Headers({ - "x-litellm-api-key": "sk-1234", + "x-litellm-api-key": masterKey, "tags": "vertex-js-sdk,pass-through-endpoint" }); @@ -113,7 +116,7 @@ describe('Vertex AI Tests', () => { await new Promise(resolve => setTimeout(resolve, 10000)); const spendResponse = await fetch( `http://127.0.0.1:4000/spend/logs?request_id=${callId}`, - { headers: { 'Authorization': 'Bearer sk-1234' } } + { headers: { 'Authorization': `Bearer ${masterKey}` } } ); spendData = await spendResponse.json(); console.log(`spendData (attempt ${attempt + 1}):`, spendData); @@ -142,7 +145,7 @@ describe('Vertex AI Tests', () => { }); const customHeaders = new Headers({ - "x-litellm-api-key": "sk-1234", + "x-litellm-api-key": masterKey, "tags": "vertex-js-sdk,pass-through-endpoint" }); @@ -190,7 +193,7 @@ describe('Vertex AI Tests', () => { await new Promise(resolve => setTimeout(resolve, 10000)); const spendResponse = await fetch( `http://127.0.0.1:4000/spend/logs?request_id=${callId}`, - { headers: { 'Authorization': 'Bearer sk-1234' } } + { headers: { 'Authorization': `Bearer ${masterKey}` } } ); spendData = await spendResponse.json(); console.log(`spendData (attempt ${attempt + 1}):`, spendData); diff --git a/tests/pass_through_unit_tests/test_claude_code_marketplace.py b/tests/pass_through_unit_tests/test_claude_code_marketplace.py index bedb8830559..2747fbbfee3 100644 --- a/tests/pass_through_unit_tests/test_claude_code_marketplace.py +++ b/tests/pass_through_unit_tests/test_claude_code_marketplace.py @@ -25,6 +25,7 @@ from litellm.proxy.anthropic_endpoints.claude_code_endpoints.claude_code_marketp register_plugin, get_marketplace, ) +from tests._master_key import MASTER_KEY class MockPluginRecord: @@ -140,7 +141,7 @@ def mock_prisma_client(): async def test_register_plugin(mock_prisma_client): """Test registering a plugin in the marketplace.""" setattr(litellm.proxy.proxy_server, "prisma_client", mock_prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -156,7 +157,7 @@ async def test_register_plugin(mock_prisma_client): user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test-user", ) @@ -190,7 +191,7 @@ async def test_register_plugin(mock_prisma_client): async def test_get_marketplace(mock_prisma_client): """Test getting marketplace.json with registered plugins.""" setattr(litellm.proxy.proxy_server, "prisma_client", mock_prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -206,7 +207,7 @@ async def test_get_marketplace(mock_prisma_client): user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test-user", ) @@ -243,7 +244,7 @@ async def test_get_marketplace(mock_prisma_client): async def test_register_plugin_git_subdir(mock_prisma_client): """Test registering a plugin with git-subdir source type.""" setattr(litellm.proxy.proxy_server, "prisma_client", mock_prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -262,7 +263,7 @@ async def test_register_plugin_git_subdir(mock_prisma_client): user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test-user", ) diff --git a/tests/proxy_admin_ui_tests/test_key_management.py b/tests/proxy_admin_ui_tests/test_key_management.py index 979ba31bffa..3516e15db2b 100644 --- a/tests/proxy_admin_ui_tests/test_key_management.py +++ b/tests/proxy_admin_ui_tests/test_key_management.py @@ -89,6 +89,7 @@ from litellm.proxy._types import ( from litellm.types.proxy.management_endpoints.ui_sso import ( LiteLLM_UpperboundKeyGenerateParams, ) +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -123,7 +124,7 @@ def prisma_client(): async def test_regenerate_api_key(prisma_client): litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # generate new key @@ -137,7 +138,7 @@ async def test_regenerate_api_key(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -164,7 +165,7 @@ async def test_regenerate_api_key(prisma_client): key=generated_key, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -219,7 +220,7 @@ async def test_regenerate_api_key(prisma_client): async def test_regenerate_api_key_with_new_alias_and_expiration(prisma_client): litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() from litellm._uuid import uuid @@ -234,7 +235,7 @@ async def test_regenerate_api_key_with_new_alias_and_expiration(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -251,7 +252,7 @@ async def test_regenerate_api_key_with_new_alias_and_expiration(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -271,7 +272,7 @@ async def test_regenerate_api_key_with_new_alias_and_expiration(prisma_client): async def test_regenerate_key_ui(prisma_client): litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() from litellm._uuid import uuid @@ -286,7 +287,7 @@ async def test_regenerate_key_ui(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -313,7 +314,7 @@ async def test_regenerate_key_ui(prisma_client): data=RegenerateKeyRequest(duration=""), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -330,7 +331,7 @@ async def test_get_users(prisma_client): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Create some test users @@ -350,7 +351,7 @@ async def test_get_users(prisma_client): user, UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -382,7 +383,7 @@ async def test_get_users_filters_dashboard_keys(prisma_client): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Create a test user @@ -397,7 +398,7 @@ async def test_get_users_filters_dashboard_keys(prisma_client): test_user, UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -467,7 +468,7 @@ async def test_get_users_key_count(prisma_client): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Create a test user with no initial keys to ensure deterministic behavior @@ -482,7 +483,7 @@ async def test_get_users_key_count(prisma_client): test_user_request, UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -512,7 +513,7 @@ async def test_get_users_key_count(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -551,7 +552,7 @@ async def test_list_teams(prisma_client): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Delete all existing teams first @@ -576,7 +577,7 @@ async def test_list_teams(prisma_client): ), http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="admin" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="admin" ), ) @@ -587,7 +588,7 @@ async def test_list_teams(prisma_client): key_alias=f"test_key_{uuid.uuid4()}", ), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="admin" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="admin" ), ) @@ -595,7 +596,7 @@ async def test_list_teams(prisma_client): teams = await list_team( http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="admin" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="admin" ), user_id=None, ) @@ -684,7 +685,7 @@ def test_team_key_generation_team_member_check(): user_api_key_dict=UserAPIKeyAuth( user_id="test_user_id", user_role=LitellmUserRoles.INTERNAL_USER, - api_key="sk-1234", + api_key=MASTER_KEY, team_member=Member(role="admin", user_id="test_user_id"), ), data=GenerateKeyRequest(), @@ -702,7 +703,7 @@ def test_team_key_generation_team_member_check(): team_table=team_table, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.INTERNAL_USER, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test_user_id", team_member=Member(role="user", user_id="test_user_id"), ), @@ -741,7 +742,7 @@ def test_key_generation_required_params_check( user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.INTERNAL_USER, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test_user_id", team_id="test_team_id", team_member=None, @@ -805,7 +806,7 @@ def test_personal_key_generation_check(): assert _personal_key_generation_check( user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="admin" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="admin" ), data=GenerateKeyRequest(), ) @@ -814,7 +815,7 @@ def test_personal_key_generation_check(): _personal_key_generation_check( user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.INTERNAL_USER, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), data=GenerateKeyRequest(), @@ -879,7 +880,7 @@ def test_prepare_metadata_fields( @pytest.mark.skip(reason="Requires reliable external DB connection (prisma).") async def test_key_update_with_model_specific_params(prisma_client): setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() from litellm.proxy._types import UpdateKeyRequest @@ -888,7 +889,7 @@ async def test_key_update_with_model_specific_params(prisma_client): data=GenerateKeyRequest(models=["gpt-4"]), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -940,7 +941,7 @@ async def test_key_update_with_model_specific_params(prisma_client): data=UpdateKeyRequest(**args), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -963,7 +964,7 @@ async def test_list_key_helper(prisma_client): # Setup - create multiple test keys setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Create test data @@ -984,7 +985,7 @@ async def test_list_key_helper(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -998,7 +999,7 @@ async def test_list_key_helper(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -1013,7 +1014,7 @@ async def test_list_key_helper(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -1097,7 +1098,7 @@ async def test_list_key_helper(prisma_client): data=KeyRequest(keys=[key.key]), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), litellm_changed_by=None, @@ -1121,7 +1122,7 @@ async def test_list_key_helper_team_filtering(prisma_client): # Setup setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Create test data with different team_ids @@ -1135,7 +1136,7 @@ async def test_list_key_helper_team_filtering(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -1150,7 +1151,7 @@ async def test_list_key_helper_team_filtering(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -1166,7 +1167,7 @@ async def test_list_key_helper_team_filtering(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -1219,7 +1220,7 @@ async def test_list_key_helper_team_filtering(prisma_client): data=KeyRequest(keys=[key.key]), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), litellm_changed_by=None, @@ -1240,7 +1241,7 @@ async def test_key_generate_always_db_team(mock_get_team_object): data=GenerateKeyRequest(team_id="1234"), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin", ), ) @@ -1271,7 +1272,7 @@ async def test_team_model_alias(prisma_client, requested_model, should_pass): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Create team with model alias @@ -1285,7 +1286,7 @@ async def test_team_model_alias(prisma_client, requested_model, should_pass): ), http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="admin" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="admin" ), ) @@ -1296,7 +1297,7 @@ async def test_team_model_alias(prisma_client, requested_model, should_pass): models=["gpt-4o-team1"], ), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="admin" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="admin" ), ) diff --git a/tests/proxy_admin_ui_tests/test_role_based_access.py b/tests/proxy_admin_ui_tests/test_role_based_access.py index 92e731b8c23..0e7df89fd04 100644 --- a/tests/proxy_admin_ui_tests/test_role_based_access.py +++ b/tests/proxy_admin_ui_tests/test_role_based_access.py @@ -76,6 +76,7 @@ verbose_proxy_logger.setLevel(level=logging.DEBUG) from litellm.caching.caching import DualCache from litellm.proxy._types import * +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -133,7 +134,7 @@ async def test_create_new_user_in_organization(prisma_client, user_role): Add a member to an organization and assert the user object is created with the correct organization memberships / roles """ - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "master_key", master_key) setattr(litellm.proxy.proxy_server, "llm_router", MagicMock()) @@ -198,7 +199,7 @@ async def test_org_admin_create_team_permissions(prisma_client): """ import json - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "master_key", master_key) setattr(litellm.proxy.proxy_server, "llm_router", MagicMock()) @@ -271,7 +272,7 @@ async def test_org_admin_create_user_permissions(prisma_client): """ import json - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "master_key", master_key) setattr(litellm.proxy.proxy_server, "llm_router", MagicMock()) @@ -344,7 +345,7 @@ async def test_org_admin_create_user_team_wrong_org_permissions(prisma_client): """ import json - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "master_key", master_key) setattr(litellm.proxy.proxy_server, "llm_router", MagicMock()) @@ -482,13 +483,13 @@ async def test_user_role_permissions(prisma_client, route, user_role, expected_r try: # Setup setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Admin - admin creates a new user user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ) diff --git a/tests/proxy_admin_ui_tests/test_usage_endpoints.py b/tests/proxy_admin_ui_tests/test_usage_endpoints.py index 0831902c290..ac104a8868d 100644 --- a/tests/proxy_admin_ui_tests/test_usage_endpoints.py +++ b/tests/proxy_admin_ui_tests/test_usage_endpoints.py @@ -100,6 +100,7 @@ from litellm.proxy._types import ( UpdateUserRequest, UserAPIKeyAuth, ) +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -133,14 +134,14 @@ def prisma_client(): async def test_view_daily_spend_ui(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() from litellm.proxy.proxy_server import user_api_key_cache spend_logs_for_admin = await global_spend_logs( user_api_key_dict=UserAPIKeyAuth( - api_key="sk-1234", + api_key=MASTER_KEY, user_role=LitellmUserRoles.PROXY_ADMIN, ), api_key=None, @@ -150,7 +151,7 @@ async def test_view_daily_spend_ui(prisma_client): spend_logs_for_internal_user = await global_spend_logs( user_api_key_dict=UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.INTERNAL_USER, user_id="1234" + api_key=MASTER_KEY, user_role=LitellmUserRoles.INTERNAL_USER, user_id="1234" ), api_key=None, ) @@ -178,7 +179,7 @@ async def test_view_daily_spend_ui(prisma_client): async def test_global_spend_models(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -186,7 +187,7 @@ async def test_global_spend_models(prisma_client): models_spend_for_admin = await global_spend_models( limit=10, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-1234", + api_key=MASTER_KEY, user_role=LitellmUserRoles.PROXY_ADMIN, ), ) @@ -197,7 +198,7 @@ async def test_global_spend_models(prisma_client): models_spend_for_internal_user = await global_spend_models( limit=10, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.INTERNAL_USER, user_id="1234" + api_key=MASTER_KEY, user_role=LitellmUserRoles.INTERNAL_USER, user_id="1234" ), ) @@ -271,7 +272,7 @@ async def test_global_spend_models(prisma_client): async def test_global_spend_keys(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -279,7 +280,7 @@ async def test_global_spend_keys(prisma_client): keys_spend_for_admin = await global_spend_keys( limit=10, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-1234", + api_key=MASTER_KEY, user_role=LitellmUserRoles.PROXY_ADMIN, ), ) @@ -290,7 +291,7 @@ async def test_global_spend_keys(prisma_client): keys_spend_for_internal_user = await global_spend_keys( limit=10, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.INTERNAL_USER, user_id="1234" + api_key=MASTER_KEY, user_role=LitellmUserRoles.INTERNAL_USER, user_id="1234" ), ) diff --git a/tests/proxy_e2e_anthropic_messages_tests/test_all_beta_headers.py b/tests/proxy_e2e_anthropic_messages_tests/test_all_beta_headers.py index 76d1ac5e9eb..f2000c6fb19 100644 --- a/tests/proxy_e2e_anthropic_messages_tests/test_all_beta_headers.py +++ b/tests/proxy_e2e_anthropic_messages_tests/test_all_beta_headers.py @@ -2,6 +2,7 @@ This test ensures that the proxy can passthrough anthropic requests """ +import os from pathlib import Path import pytest import aiohttp @@ -46,7 +47,7 @@ async def test_anthropic_messages_with_all_beta_headers(model_name, provider_nam print("Testing v1/messages with all non-null Anthropic beta headers") headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", "anthropic-version": "2023-06-01", "anthropic-beta": ",".join( @@ -115,7 +116,7 @@ async def test_bedrock_invoke_messages_with_all_beta_headers(model_name, provide beta_headers = get_all_supported_anthropic_beta_headers(provider_name) headers = { - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json", "anthropic-version": "2023-06-01", "anthropic-beta": ",".join(beta_headers), diff --git a/tests/proxy_e2e_anthropic_messages_tests/test_claude_agent_sdk.py b/tests/proxy_e2e_anthropic_messages_tests/test_claude_agent_sdk.py index c1339ce6280..f29d938517f 100644 --- a/tests/proxy_e2e_anthropic_messages_tests/test_claude_agent_sdk.py +++ b/tests/proxy_e2e_anthropic_messages_tests/test_claude_agent_sdk.py @@ -29,7 +29,7 @@ TEST_MODELS = [ def litellm_proxy_config(): """Configure connection to LiteLLM proxy""" proxy_url = os.getenv("LITELLM_PROXY_URL", "http://localhost:4000") - api_key = os.getenv("LITELLM_API_KEY", "sk-1234") + api_key = os.environ["LITELLM_API_KEY"] # Set environment variables for Claude Agent SDK os.environ["ANTHROPIC_BASE_URL"] = proxy_url.rstrip("/") diff --git a/tests/proxy_migration_tests/test_component_image_serves_offline.py b/tests/proxy_migration_tests/test_component_image_serves_offline.py index 528c2960072..c2f0d1e5406 100644 --- a/tests/proxy_migration_tests/test_component_image_serves_offline.py +++ b/tests/proxy_migration_tests/test_component_image_serves_offline.py @@ -32,6 +32,8 @@ import uuid import os import pytest +from tests._master_key import MASTER_KEY + IMAGE = os.getenv("LITELLM_IMAGE") POSTGRES_IMAGE = os.getenv("LITELLM_TEST_POSTGRES_IMAGE", "postgres:16-alpine") CURL_IMAGE = os.getenv("LITELLM_TEST_CURL_IMAGE", "curlimages/curl:8.11.1") @@ -89,7 +91,7 @@ def offline_stack(): "run", "-d", "--name", component, "--network", network, "--user", NON_ROOT_UID, "-e", f"DATABASE_URL=postgresql://postgres:pw@{pg}:5432/litellm", - "-e", "LITELLM_MASTER_KEY=sk-component-serve-test", + "-e", f"LITELLM_MASTER_KEY={MASTER_KEY}", "-e", "DISABLE_SCHEMA_UPDATE=true", "-e", "LITELLM_LOCAL_MODEL_COST_MAP=True", IMAGE, diff --git a/tests/proxy_security_tests/test_master_key_not_in_db.py b/tests/proxy_security_tests/test_master_key_not_in_db.py index 2f00e57037a..1eaaafae708 100644 --- a/tests/proxy_security_tests/test_master_key_not_in_db.py +++ b/tests/proxy_security_tests/test_master_key_not_in_db.py @@ -3,8 +3,7 @@ import pytest from fastapi.testclient import TestClient from litellm.proxy.proxy_server import app, ProxyLogging, hash_token from litellm.caching import DualCache - -MASTER_KEY = "sk-1234" +from tests._master_key import MASTER_KEY @pytest.fixture(autouse=True) diff --git a/tests/proxy_unit_tests/test_proxy_server_gemini_pass_through.py b/tests/proxy_unit_tests/test_proxy_server_gemini_pass_through.py index 2453ec3bfe3..97d6b5c7cf3 100644 --- a/tests/proxy_unit_tests/test_proxy_server_gemini_pass_through.py +++ b/tests/proxy_unit_tests/test_proxy_server_gemini_pass_through.py @@ -29,7 +29,7 @@ async def test_gemini_pass_through_endpoint(): "type": "http", "method": "POST", "path": "/gemini/v1beta/models/gemini-2.5-flash:countTokens", - "query_string": b"key=sk-1234", + "query_string": b"key=sk-9876", "headers": [ (b"content-type", b"application/json"), ], @@ -44,8 +44,7 @@ async def test_gemini_pass_through_endpoint(): ) await gemini_proxy_route( - endpoint="v1beta/models/gemini-2.5-flash:countTokens?key=sk-1234", + endpoint="v1beta/models/gemini-2.5-flash:countTokens?key=sk-9876", request=request, fastapi_response=Response(), ) - diff --git a/tests/store_model_in_db_tests/test_adding_passthrough_model.py b/tests/store_model_in_db_tests/test_adding_passthrough_model.py index 001b0c941a5..20df78646a7 100644 --- a/tests/store_model_in_db_tests/test_adding_passthrough_model.py +++ b/tests/store_model_in_db_tests/test_adding_passthrough_model.py @@ -15,7 +15,7 @@ import httpx import os import json -TEST_MASTER_KEY = "sk-1234" +TEST_MASTER_KEY = os.environ["LITELLM_MASTER_KEY"] PROXY_BASE_URL = "http://0.0.0.0:4000" US_BASE_URL = f"{PROXY_BASE_URL}/assemblyai" ASSEMBLYAI_API_KEY_ENV_VAR = "ASSEMBLYAI_API_KEY" diff --git a/tests/store_model_in_db_tests/test_mcp_servers.py b/tests/store_model_in_db_tests/test_mcp_servers.py index 5c1a996b276..482e2724482 100644 --- a/tests/store_model_in_db_tests/test_mcp_servers.py +++ b/tests/store_model_in_db_tests/test_mcp_servers.py @@ -34,7 +34,7 @@ from litellm.proxy.management_endpoints.mcp_management_endpoints import ( does_mcp_server_exist, ) -TEST_MASTER_KEY = os.getenv("LITELLM_MASTER_KEY", "sk-1234") +TEST_MASTER_KEY = os.environ["LITELLM_MASTER_KEY"] def generate_mcpserver_record( diff --git a/tests/store_model_in_db_tests/test_openai_error_handling.py b/tests/store_model_in_db_tests/test_openai_error_handling.py index 22707d522bc..984f103e14d 100644 --- a/tests/store_model_in_db_tests/test_openai_error_handling.py +++ b/tests/store_model_in_db_tests/test_openai_error_handling.py @@ -1,3 +1,5 @@ +import os + import pytest from openai import OpenAI, BadRequestError, AsyncOpenAI import asyncio @@ -6,7 +8,7 @@ import httpx def generate_key_sync(): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} with httpx.Client() as client: response = client.post( @@ -92,10 +94,10 @@ async def test_async_chat_completion_bad_model(): @pytest.mark.parametrize( "curl_command", [ - 'curl http://0.0.0.0:4000/v1/chat/completions -H \'Content-Type: application/json\' -H \'Authorization: Bearer sk-1234\' -d \'{"messages":[{"role":"user","content":"Hello!"}]}\'', - "curl http://0.0.0.0:4000/v1/completions -H 'Content-Type: application/json' -H 'Authorization: Bearer sk-1234' -d '{\"prompt\":\"Hello!\"}'", - "curl http://0.0.0.0:4000/v1/embeddings -H 'Content-Type: application/json' -H 'Authorization: Bearer sk-1234' -d '{\"input\":\"Hello world\"}'", - "curl http://0.0.0.0:4000/v1/images/generations -H 'Content-Type: application/json' -H 'Authorization: Bearer sk-1234' -d '{\"prompt\":\"A cute baby sea otter\"}'", + 'curl http://0.0.0.0:4000/v1/chat/completions -H \'Content-Type: application/json\' -H "Authorization: Bearer sk-9876" -d \'{"messages":[{"role":"user","content":"Hello!"}]}\'', + "curl http://0.0.0.0:4000/v1/completions -H 'Content-Type: application/json' -H \"Authorization: Bearer sk-9876\" -d '{\"prompt\":\"Hello!\"}'", + "curl http://0.0.0.0:4000/v1/embeddings -H 'Content-Type: application/json' -H \"Authorization: Bearer sk-9876\" -d '{\"input\":\"Hello world\"}'", + "curl http://0.0.0.0:4000/v1/images/generations -H 'Content-Type: application/json' -H \"Authorization: Bearer sk-9876\" -d '{\"prompt\":\"A cute baby sea otter\"}'", ], ids=["chat", "completions", "embeddings", "images"], ) @@ -105,7 +107,7 @@ def test_missing_model_parameter_curl(curl_command): # Run the curl command and capture the output key = generate_key_sync() - curl_command = curl_command.replace("sk-1234", key) + curl_command = curl_command.replace("sk-9876", key) result = subprocess.run( f'{curl_command} -s -w "\\n%{{http_code}}"', shell=True, @@ -168,7 +170,7 @@ async def test_chat_completion_bad_model_with_spend_logs(): # Now query the spend logs url = "http://0.0.0.0:4000/spend/logs?request_id=" + litellm_call_id - headers = {"Authorization": f"Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} with httpx.Client() as client: response = client.get( diff --git a/tests/store_model_in_db_tests/test_team_metadata_validation_e2e.py b/tests/store_model_in_db_tests/test_team_metadata_validation_e2e.py index 050b59ef426..1a2300f5e9d 100644 --- a/tests/store_model_in_db_tests/test_team_metadata_validation_e2e.py +++ b/tests/store_model_in_db_tests/test_team_metadata_validation_e2e.py @@ -16,7 +16,7 @@ import httpx import pytest PROXY_BASE_URL = os.getenv("PROXY_BASE_URL", "http://localhost:4000") -MASTER_KEY = os.getenv("LITELLM_MASTER_KEY", "sk-1234") +MASTER_KEY = os.environ["LITELLM_MASTER_KEY"] HEADERS = {"Authorization": f"Bearer {MASTER_KEY}", "Content-Type": "application/json"} UNAVAILABLE_MESSAGE = "Cost center validation is unavailable right now; the team was not saved. Contact FinOps." diff --git a/tests/test_budget_management.py b/tests/test_budget_management.py index 645de3d412d..42d5c5d98ac 100644 --- a/tests/test_budget_management.py +++ b/tests/test_budget_management.py @@ -1,3 +1,4 @@ +import os # What is this? ## Unit tests for the /budget/* endpoints from litellm._uuid import uuid @@ -23,7 +24,7 @@ def _parse_budget_api_datetime(value: str) -> datetime: async def delete_budget(session, budget_id): url = "http://0.0.0.0:4000/budget/delete" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"id": budget_id} async with session.post(url, headers=headers, json=data) as response: assert response.status == 200 @@ -32,7 +33,7 @@ async def delete_budget(session, budget_id): async def create_budget(session, data): url = "http://0.0.0.0:4000/budget/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} async with session.post(url, headers=headers, json=data) as response: assert response.status == 200 diff --git a/tests/test_callbacks_on_proxy.py b/tests/test_callbacks_on_proxy.py index 130ce773b1f..42aa6d98cb9 100644 --- a/tests/test_callbacks_on_proxy.py +++ b/tests/test_callbacks_on_proxy.py @@ -160,7 +160,7 @@ async def _sample_callbacks(session, num_samples, interval): async def config_update(session, routing_strategy=None): url = "http://0.0.0.0:4000/config/update" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} print("routing_strategy: ", routing_strategy) data = { "router_settings": { @@ -188,7 +188,7 @@ async def get_active_callbacks(session): url = "http://0.0.0.0:4000/active/callbacks" headers = { "Content-Type": "application/json", - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", } async with session.get(url, headers=headers) as response: @@ -216,7 +216,7 @@ async def get_current_routing_strategy(session): url = "http://0.0.0.0:4000/get/config/callbacks" headers = { "Content-Type": "application/json", - "Authorization": "Bearer sk-1234", + "Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", } async with session.get(url, headers=headers) as response: diff --git a/tests/test_end_users.py b/tests/test_end_users.py index a7ee5c48f90..03fb4c9e86c 100644 --- a/tests/test_end_users.py +++ b/tests/test_end_users.py @@ -1,3 +1,4 @@ +import os # What is this? ## Unit tests for the /end_users/* endpoints import pytest @@ -23,7 +24,7 @@ async def generate_key( max_parallel_requests: Optional[int] = None, user_id: Optional[str] = None, team_id: Optional[str] = None, - calling_key="sk-1234", + calling_key=os.environ["LITELLM_MASTER_KEY"], ): url = "http://0.0.0.0:4000/key/generate" headers = { @@ -66,7 +67,7 @@ async def new_end_user( budget_id=None, ): url = "http://0.0.0.0:4000/end_user/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "user_id": user_id, "allowed_model_region": model_region, @@ -93,7 +94,7 @@ async def new_end_user( async def new_budget(session, i, budget_id=None): url = "http://0.0.0.0:4000/budget/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "budget_id": budget_id, "tpm_limit": 2, @@ -188,7 +189,7 @@ async def test_enduser_tpm_limits_with_master_key(): # chat completion 1 client = AsyncOpenAI( - api_key="sk-1234", base_url="http://0.0.0.0:4000", max_retries=0 + api_key=os.environ["LITELLM_MASTER_KEY"], base_url="http://0.0.0.0:4000", max_retries=0 ) # chat completion 2 diff --git a/tests/test_fallbacks.py b/tests/test_fallbacks.py index 0db5d168f5b..8418847d062 100644 --- a/tests/test_fallbacks.py +++ b/tests/test_fallbacks.py @@ -18,7 +18,7 @@ async def generate_key( session, i, models: list, - calling_key="sk-1234", + calling_key=os.environ["LITELLM_MASTER_KEY"], ): url: Final = f"{PROXY_BASE_URL}/key/generate" headers = { @@ -123,7 +123,7 @@ async def test_chat_completion_with_retries(): ] response, headers = await chat_completion( session=session, - key="sk-1234", + key=os.environ["LITELLM_MASTER_KEY"], model=model, messages=messages, mock_testing_rate_limit_error=True, @@ -147,7 +147,7 @@ async def test_chat_completion_with_fallbacks(): ] response, headers = await chat_completion( session=session, - key="sk-1234", + key=os.environ["LITELLM_MASTER_KEY"], model=model, messages=messages, fallbacks=["fake-openai-endpoint-5"], @@ -171,7 +171,7 @@ async def test_chat_completion_with_timeout(): start_time = time.time() response, headers = await chat_completion( session=session, - key="sk-1234", + key=os.environ["LITELLM_MASTER_KEY"], model=model, messages=messages, num_retries=0, @@ -202,7 +202,7 @@ async def test_chat_completion_with_timeout_from_request(): start_time = time.time() response, headers = await chat_completion( session=session, - key="sk-1234", + key=os.environ["LITELLM_MASTER_KEY"], model=model, messages=messages, num_retries=0, @@ -305,7 +305,7 @@ async def test_chat_completion_bad_and_good_model(): """ Prod test - ensure even if bad model is down, good model is still working. """ - client = AsyncOpenAI(api_key="sk-1234", base_url="http://0.0.0.0:4000") + client = AsyncOpenAI(api_key=os.environ["LITELLM_MASTER_KEY"], base_url="http://0.0.0.0:4000") num_requests = 100 num_iterations = 3 diff --git a/tests/test_health.py b/tests/test_health.py index cc551fd9380..c553f68b559 100644 --- a/tests/test_health.py +++ b/tests/test_health.py @@ -1,3 +1,5 @@ +import os + # What this tests? ## Tests /health + /routes endpoints. @@ -29,7 +31,10 @@ async def health(session, call_key): async def generate_key(session): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = { + "Authorization": "Bearer " + os.environ["LITELLM_MASTER_KEY"], + "Content-Type": "application/json", + } data = { "models": ["gpt-4", "text-embedding-ada-002", "gpt-image-1"], "duration": None, @@ -54,7 +59,7 @@ async def test_health(): """ async with aiohttp.ClientSession() as session: # as admin # - all_healthy_models = await health(session=session, call_key="sk-1234") + all_healthy_models = await health(session=session, call_key=os.environ["LITELLM_MASTER_KEY"]) total_model_count = ( all_healthy_models["healthy_count"] + all_healthy_models["unhealthy_count"] ) @@ -86,7 +91,7 @@ async def test_health_readiness_details(): """ async with aiohttp.ClientSession() as session: url = "http://0.0.0.0:4000/health/readiness/details" - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer " + os.environ["LITELLM_MASTER_KEY"]} async with session.get(url, headers=headers) as response: status = response.status response_json = await response.json() diff --git a/tests/test_keys.py b/tests/test_keys.py index 67aae0ae848..f445044d990 100644 --- a/tests/test_keys.py +++ b/tests/test_keys.py @@ -16,7 +16,7 @@ async def generate_team( session, models: Optional[list] = None, team_id: Optional[str] = None ): url = "http://0.0.0.0:4000/team/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} if team_id is None: team_id = "litellm-dashboard" data = {"team_id": team_id, **({"models": models} if models is not None else {})} @@ -37,7 +37,7 @@ async def generate_user( user_role="app_owner", ): url = "http://0.0.0.0:4000/user/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "user_role": user_role, "team_id": "litellm-dashboard", @@ -64,7 +64,7 @@ async def generate_key( user_id: Optional[str] = None, team_id: Optional[str] = None, metadata: Optional[dict] = None, - calling_key="sk-1234", + calling_key=os.environ["LITELLM_MASTER_KEY"], ): url = "http://0.0.0.0:4000/key/generate" headers = { @@ -125,7 +125,7 @@ async def test_key_gen_bad_key(): """ async with aiohttp.ClientSession() as session: ## LOGIN TO UI - form_data = {"username": "admin", "password": "sk-1234"} + form_data = {"username": "admin", "password": os.environ["LITELLM_MASTER_KEY"]} async with session.post( "http://0.0.0.0:4000/login", data=form_data ) as response: @@ -210,7 +210,7 @@ async def chat_completion_streaming(session, key, model="gpt-4"): return prompt_tokens, completion_tokens -async def delete_key(session, get_key, auth_key="sk-1234"): +async def delete_key(session, get_key, auth_key=os.environ["LITELLM_MASTER_KEY"]): """ Delete key """ @@ -334,7 +334,7 @@ async def test_key_info(): key_gen = await generate_key(session=session, i=0) key = key_gen["key"] # as admin # - await get_key_info(session=session, get_key=key, call_key="sk-1234") + await get_key_info(session=session, get_key=key, call_key=os.environ["LITELLM_MASTER_KEY"]) # as key itself # await get_key_info(session=session, get_key=key, call_key=key) @@ -355,7 +355,7 @@ async def test_model_info(): key_gen = await generate_key(session=session, i=0) key = key_gen["key"] # as admin # - admin_models = await get_model_info(session=session, call_key="sk-1234") + admin_models = await get_model_info(session=session, call_key=os.environ["LITELLM_MASTER_KEY"]) admin_models = admin_models["data"] # as key itself # user_models = await get_model_info(session=session, call_key=key) @@ -367,7 +367,7 @@ async def test_model_info(): async def get_spend_logs(session, request_id): url = f"http://0.0.0.0:4000/spend/logs?request_id={request_id}" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} async with session.get(url, headers=headers) as response: status = response.status diff --git a/tests/test_models.py b/tests/test_models.py index c68659545b8..14706098f27 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -14,7 +14,7 @@ load_dotenv() async def generate_key(session, models=[]): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": models, "duration": None, @@ -73,7 +73,7 @@ async def test_get_models_multiple_tests(): async def add_models( - session, model_id="123", model_name="azure-gpt-3.5", key="sk-1234", team_id=None + session, model_id="123", model_name="azure-gpt-3.5", key=os.environ["LITELLM_MASTER_KEY"], team_id=None ): url = "http://0.0.0.0:4000/model/new" headers = { @@ -216,7 +216,7 @@ async def test_get_specific_model(): ) -async def delete_model(session, model_id="123", key="sk-1234"): +async def delete_model(session, model_id="123", key=os.environ["LITELLM_MASTER_KEY"]): """ Make sure only models user has access to are returned """ @@ -296,10 +296,10 @@ async def test_model_group_info_e2e(): Test /model/group/info endpoint """ async with aiohttp.ClientSession() as session: - models = await get_models(session=session, key="sk-1234") + models = await get_models(session=session, key=os.environ["LITELLM_MASTER_KEY"]) print(models) - model_group_info = await get_model_group_info(session=session, key="sk-1234") + model_group_info = await get_model_group_info(session=session, key=os.environ["LITELLM_MASTER_KEY"]) print(model_group_info) model_groups: Final = [m["model_group"] for m in model_group_info["data"]] diff --git a/tests/test_openai_endpoints.py b/tests/test_openai_endpoints.py index 16f8de65236..6b92373a98c 100644 --- a/tests/test_openai_endpoints.py +++ b/tests/test_openai_endpoints.py @@ -8,7 +8,7 @@ import aiohttp, openai from openai import OpenAI, AsyncOpenAI, AzureOpenAI, AsyncAzureOpenAI from typing import Optional, List, Union -LITELLM_MASTER_KEY = "sk-1234" +LITELLM_MASTER_KEY = os.environ["LITELLM_MASTER_KEY"] def response_header_check(response): @@ -30,7 +30,7 @@ async def generate_key( ], ): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": models, "duration": None, @@ -55,7 +55,7 @@ async def generate_key( async def new_user(session): url = "http://0.0.0.0:4000/user/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": ["gpt-4", "text-embedding-ada-002", "gpt-image-1"], "duration": None, @@ -323,7 +323,7 @@ async def test_chat_completion_ratelimit(): """ async with aiohttp.ClientSession() as session: # key_gen = await generate_key(session=session) - key = "sk-1234" + key = os.environ["LITELLM_MASTER_KEY"] tasks = [] tasks.append( chat_completion(session=session, key=key, model="fake-openai-endpoint-2") @@ -351,7 +351,7 @@ async def test_chat_completion_different_deployments(): """ async with aiohttp.ClientSession() as session: # key_gen = await generate_key(session=session) - key = "sk-1234" + key = os.environ["LITELLM_MASTER_KEY"] results = [] for _ in range(20): results.append( @@ -377,7 +377,7 @@ async def test_chat_completion_streaming(): """ [PROD Test] Ensures logprobs are returned correctly """ - client = AsyncOpenAI(api_key="sk-1234", base_url="http://0.0.0.0:4000") + client = AsyncOpenAI(api_key=os.environ["LITELLM_MASTER_KEY"], base_url="http://0.0.0.0:4000") response = await client.chat.completions.create( model="gpt-3.5-turbo-large", @@ -401,7 +401,7 @@ async def test_completion_streaming_usage_metrics(): [PROD Test] Ensures usage metrics are returned correctly when `include_usage` is set to `True` """ client: Final = AsyncOpenAI( - api_key="sk-1234", base_url=os.environ.get("LITELLM_PROXY_BASE_URL", "http://0.0.0.0:4000") + api_key=os.environ["LITELLM_MASTER_KEY"], base_url=os.environ.get("LITELLM_PROXY_BASE_URL", "http://0.0.0.0:4000") ) response = await client.completions.create( @@ -458,7 +458,7 @@ async def test_batch_chat_completions(): # call chat/completions with a model that the key was not created for + the model is not on the config.yaml response = await chat_completion( session=session, - key="sk-1234", + key=os.environ["LITELLM_MASTER_KEY"], model="gpt-3.5-turbo,fake-openai-endpoint", ) diff --git a/tests/test_spend_logs.py b/tests/test_spend_logs.py index 4c6a984a5cf..503db8202b7 100644 --- a/tests/test_spend_logs.py +++ b/tests/test_spend_logs.py @@ -1,3 +1,4 @@ +import os # What this tests? ## Tests /spend endpoints. @@ -8,7 +9,7 @@ import aiohttp async def generate_key(session, models=[], team_id=None): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": models, "duration": None, @@ -86,7 +87,7 @@ async def get_spend_logs(session, request_id=None, api_key=None): url = f"http://0.0.0.0:4000/spend/logs?api_key={api_key}" else: url = f"http://0.0.0.0:4000/spend/logs?request_id={request_id}" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} async with session.get(url, headers=headers) as response: status = response.status @@ -129,7 +130,7 @@ async def generate_org(session: aiohttp.ClientSession) -> dict: dict: Response containing org_id """ url = "http://0.0.0.0:4000/organization/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} request_body = { "organization_alias": f"test-org-{uuid.uuid4()}", @@ -151,7 +152,7 @@ async def generate_team(session: aiohttp.ClientSession, org_id: str) -> dict: dict: Response containing team_id """ url = "http://0.0.0.0:4000/team/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"organization_id": org_id} async with session.post(url, headers=headers, json=data) as response: @@ -198,7 +199,7 @@ async def test_spend_logs_with_org_id(): async def get_predict_spend_logs(session): url = "http://0.0.0.0:4000/global/predict/spend/logs" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "data": [ { diff --git a/tests/test_team.py b/tests/test_team.py index ecf41b1bd57..e7b5d0cac6d 100644 --- a/tests/test_team.py +++ b/tests/test_team.py @@ -1,3 +1,4 @@ +import os # What this tests ? ## Tests /team endpoints. import pytest @@ -50,7 +51,7 @@ async def wait_for_team_member_spend_update( initial_spend = None while time.time() - start_time < max_wait: try: - user_info = await get_user_info(session, user_id, call_user="sk-1234") + user_info = await get_user_info(session, user_id, call_user=os.environ["LITELLM_MASTER_KEY"]) if user_info.get("teams"): for team in user_info["teams"]: if team.get("team_id") == team_id: @@ -90,7 +91,7 @@ async def new_user( user_email=None, ): url = "http://localhost:4000/user/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": models, "aliases": {"mistral-7b": "gpt-3.5-turbo"}, @@ -126,7 +127,7 @@ async def add_member( session, i, team_id, user_id=None, user_email=None, max_budget=None, members=None ): url = "http://localhost:4000/team/member_add" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"team_id": team_id, "member": {"role": "user"}} if user_email is not None: data["member"]["user_email"] = user_email @@ -162,7 +163,7 @@ async def update_member( max_budget=None, ): url = "http://localhost:4000/team/member_update" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"team_id": team_id} if user_id is not None: data["user_id"] = user_id @@ -191,7 +192,7 @@ async def update_member( async def delete_member(session, i, team_id, user_id=None, user_email=None): url = "http://localhost:4000/team/member_delete" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"team_id": team_id} if user_id is not None: data["user_id"] = user_id @@ -221,7 +222,7 @@ async def generate_key( team_id=None, ): url = "http://localhost:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": models, "duration": None, @@ -287,7 +288,7 @@ async def new_team(session, i, user_id=None, member_list=None, model_aliases=Non import json url = "http://localhost:4000/team/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"team_alias": "my-new-team"} if user_id is not None: data["members_with_roles"] = [{"role": "user", "user_id": user_id}] @@ -315,7 +316,7 @@ async def new_team(session, i, user_id=None, member_list=None, model_aliases=Non async def update_team(session, i, team_id, user_id=None, member_list=None, **kwargs): url = "http://localhost:4000/team/update" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = {"team_id": team_id, **kwargs} if user_id is not None: data["members_with_roles"] = [{"role": "user", "user_id": user_id}] @@ -342,7 +343,7 @@ async def delete_team( team_id, ): url = "http://localhost:4000/team/delete" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "team_ids": [team_id], } @@ -366,7 +367,7 @@ async def list_teams( i, ): url = "http://localhost:4000/team/list" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} async with session.get(url, headers=headers) as response: status = response.status @@ -431,7 +432,7 @@ async def test_team_info(): ) team_id = new_team_data["team_id"] ## as admin ## - await get_team_info(session=session, get_team=team_id, call_key="sk-1234") + await get_team_info(session=session, get_team=team_id, call_key=os.environ["LITELLM_MASTER_KEY"]) """ Scenario 2 - as team key """ @@ -496,7 +497,7 @@ async def test_team_update_sc_2(): ) ## ASSERT TEAM SIZE team_info = await get_team_info( - session=session, get_team=team_data["team_id"], call_key="sk-1234" + session=session, get_team=team_data["team_id"], call_key=os.environ["LITELLM_MASTER_KEY"] ) assert len(team_info["team_info"]["members_with_roles"]) == 12 @@ -557,7 +558,7 @@ async def test_team_member_add_email(): ## check user info to confirm user is in team updated_user_info = await get_user_info( - session=session, get_user=new_user_info["user_id"], call_user="sk-1234" + session=session, get_user=new_user_info["user_id"], call_user=os.environ["LITELLM_MASTER_KEY"] ) print(updated_user_info) @@ -594,7 +595,7 @@ async def test_team_delete(): ## ASSERT USER MEMBERSHIP IS CREATED user_info = await get_user_info( - session=session, get_user=normal_user, call_user="sk-1234" + session=session, get_user=normal_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) assert len(user_info["teams"]) == 1 @@ -608,14 +609,14 @@ async def test_team_delete(): ## ASSERT USER MEMBERSHIP IS DELETED user_info = await get_user_info( - session=session, get_user=normal_user, call_user="sk-1234" + session=session, get_user=normal_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) assert len(user_info["teams"]) == 0 ## ASSERT TEAM INFO NOW RETURNS A 404 with pytest.raises(openai.NotFoundError): await get_team_info( - session=session, get_team=team_data["team_id"], call_key="sk-1234" + session=session, get_team=team_data["team_id"], call_key=os.environ["LITELLM_MASTER_KEY"] ) @@ -729,7 +730,7 @@ async def test_users_in_team_budget(): print(f"[DEBUG] Key team_id: {team['team_id']}") # Check user info BEFORE updating member budget - user_info_before = await get_user_info(session, get_user, call_user="sk-1234") + user_info_before = await get_user_info(session, get_user, call_user=os.environ["LITELLM_MASTER_KEY"]) print(f"[DEBUG] User info BEFORE update_member:") print(f" - User budget: {user_info_before.get('max_budget')}") print(f" - User spend: {user_info_before.get('spend')}") @@ -746,7 +747,7 @@ async def test_users_in_team_budget(): print(f"[DEBUG] Update result: {update_result}") # Check user info AFTER updating member budget - user_info_after = await get_user_info(session, get_user, call_user="sk-1234") + user_info_after = await get_user_info(session, get_user, call_user=os.environ["LITELLM_MASTER_KEY"]) print(f"[DEBUG] User info AFTER update_member:") print(f" - User budget: {user_info_after.get('max_budget')}") print(f" - User spend: {user_info_after.get('spend')}") @@ -790,7 +791,7 @@ async def test_users_in_team_budget(): # Check user info BEFORE Call 2 user_info_before_call2 = await get_user_info( - session, get_user, call_user="sk-1234" + session, get_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) print(f"\n[DEBUG] User info BEFORE Call 2:") print(f" - User budget: {user_info_before_call2.get('max_budget')}") @@ -855,7 +856,7 @@ async def test_users_in_team_budget(): # Check user info AFTER Call 2 user_info_after_call2 = await get_user_info( - session, get_user, call_user="sk-1234" + session, get_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) print(f"\n[DEBUG] User info AFTER Call 2:") print(f" - User budget: {user_info_after_call2.get('max_budget')}") @@ -901,7 +902,7 @@ async def test_users_in_team_budget(): print("[DEBUG] Call 2 failed as expected with budget exceeded error") ## Check user info - user_info = await get_user_info(session, get_user, call_user="sk-1234") + user_info = await get_user_info(session, get_user, call_user=os.environ["LITELLM_MASTER_KEY"]) assert ( user_info["teams"][0]["team_memberships"][0]["litellm_budget_table"][ diff --git a/tests/test_team_logging.py b/tests/test_team_logging.py index 86b357d9d4a..94aa46260fc 100644 --- a/tests/test_team_logging.py +++ b/tests/test_team_logging.py @@ -13,7 +13,7 @@ load_dotenv() async def generate_key(session, models=[], team_id=None): url = "http://0.0.0.0:4000/key/generate" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": models, "duration": None, diff --git a/tests/test_team_members.py b/tests/test_team_members.py index 42bf0527993..49dc848661b 100644 --- a/tests/test_team_members.py +++ b/tests/test_team_members.py @@ -1,3 +1,4 @@ +import os import pytest import requests import time @@ -77,7 +78,7 @@ class TeamAPI: def api_client(): """Fixture for TeamAPI client""" base_url = "http://localhost:4000" - auth_token = "sk-1234" # Replace with your token + auth_token = os.environ["LITELLM_MASTER_KEY"] # Replace with your token return TeamAPI(base_url, auth_token) diff --git a/tests/test_users.py b/tests/test_users.py index c4a0dadf346..f1e1a59f8db 100644 --- a/tests/test_users.py +++ b/tests/test_users.py @@ -1,3 +1,4 @@ +import os # What this tests ? ## Tests /user endpoints. import pytest @@ -14,7 +15,7 @@ async def new_user( session, i, user_id=None, budget=None, budget_duration=None, models=None ): url = "http://0.0.0.0:4000/user/new" - headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} + headers = {"Authorization": f"Bearer {os.environ['LITELLM_MASTER_KEY']}", "Content-Type": "application/json"} data = { "models": models or ["azure-models"], "aliases": {"mistral-7b": "gpt-3.5-turbo"}, @@ -92,7 +93,7 @@ async def test_user_info(): key = key_gen["key"] ## as admin ## resp = await get_user_info( - session=session, get_user=get_user, call_user="sk-1234" + session=session, get_user=get_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) assert isinstance(resp["user_info"], dict) assert len(resp["user_info"]) > 0 @@ -194,21 +195,21 @@ async def test_global_proxy_budget_update(): get_user = f"litellm-proxy-budget" async with aiohttp.ClientSession() as session: user_info = await get_user_info( - session=session, get_user=get_user, call_user="sk-1234" + session=session, get_user=get_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) original_spend = user_info["user_info"]["spend"] - await chat_completion(session=session, key="sk-1234") + await chat_completion(session=session, key=os.environ["LITELLM_MASTER_KEY"]) await asyncio.sleep(5) # let db update user_info = await get_user_info( - session=session, get_user=get_user, call_user="sk-1234" + session=session, get_user=get_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) new_spend = user_info["user_info"]["spend"] print(f"new_spend: {new_spend}; original_spend: {original_spend}") assert new_spend > original_spend - await chat_completion_streaming(session=session, key="sk-1234") + await chat_completion_streaming(session=session, key=os.environ["LITELLM_MASTER_KEY"]) await asyncio.sleep(5) # let db update user_info = await get_user_info( - session=session, get_user=get_user, call_user="sk-1234" + session=session, get_user=get_user, call_user=os.environ["LITELLM_MASTER_KEY"] ) new_new_spend = user_info["user_info"]["spend"] print(f"new_spend: {new_spend}; original_spend: {original_spend}") diff --git a/tests/unified_google_tests/conftest.py b/tests/unified_google_tests/conftest.py index 9eac5f49651..ad0e135ec04 100644 --- a/tests/unified_google_tests/conftest.py +++ b/tests/unified_google_tests/conftest.py @@ -7,12 +7,14 @@ import socket import threading import time from pathlib import Path -from typing import Iterator, Tuple +from typing import Final, Iterator, Tuple import pytest import uvicorn from dotenv import load_dotenv +from tests._master_key import MASTER_KEY + load_dotenv() import litellm # noqa: E402,F401 @@ -34,7 +36,7 @@ from tests._vcr_conftest_common import ( # noqa: E402,F401 _verbose_state = VerboseReporterState() PROXY_CONFIG_PATH = Path(__file__).parent / "google_genai_proxy_test_config.yaml" -PROXY_MASTER_KEY = "sk-unified-google-tests-4f9b2c7d8e1a" +PROXY_MASTER_KEY: Final = MASTER_KEY PROXY_START_TIMEOUT_S = 30.0 diff --git a/tests/unified_google_tests/google_genai_proxy_test_config.yaml b/tests/unified_google_tests/google_genai_proxy_test_config.yaml index 99f24e62916..268ab2028f8 100644 --- a/tests/unified_google_tests/google_genai_proxy_test_config.yaml +++ b/tests/unified_google_tests/google_genai_proxy_test_config.yaml @@ -14,7 +14,7 @@ router_settings: RateLimitErrorRetries: 5 general_settings: - master_key: sk-unified-google-tests-4f9b2c7d8e1a + master_key: os.environ/LITELLM_MASTER_KEY store_model_in_db: false litellm_settings: diff --git a/tests/unit/enterprise/enterprise_callbacks/test_llm_guard.py b/tests/unit/enterprise/enterprise_callbacks/test_llm_guard.py index 5695b184479..fd9c5496917 100644 --- a/tests/unit/enterprise/enterprise_callbacks/test_llm_guard.py +++ b/tests/unit/enterprise/enterprise_callbacks/test_llm_guard.py @@ -40,7 +40,7 @@ async def test_llm_guard_call_type_aliases( "is_valid": is_valid, }, ) - user_api_key_dict: Final = UserAPIKeyAuth(api_key=hash_token("sk-12345")) + user_api_key_dict: Final = UserAPIKeyAuth(api_key=hash_token("sk-98765")) data: Final = { payload_key: [{"role": "user", "content": "email: person@example.com"}] if payload_key == "messages" diff --git a/tests/unit/enterprise/enterprise_callbacks/test_secret_detection.py b/tests/unit/enterprise/enterprise_callbacks/test_secret_detection.py index 405136924e7..3bdeb34c2fe 100644 --- a/tests/unit/enterprise/enterprise_callbacks/test_secret_detection.py +++ b/tests/unit/enterprise/enterprise_callbacks/test_secret_detection.py @@ -29,7 +29,7 @@ from litellm.proxy._types import UserAPIKeyAuth AWS_KEY = "AKIAIOSFODNN7EXAMPLE" OPENAI_KEY = "sk-test-abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGH" -SHORT_OPENAI_KEY = "sk-12345" +SHORT_OPENAI_KEY = "sk-98765" UNICODE_DIGIT_SUFFIX = "sk-notification٣" STRIPE_LIVE_KEY = f"sk_live_{'1234567890' * 3}" URL_ENCODED_KEY = "Bearer%20sk-Ab3dEf6Gh7Ij8Kl9Mn0Pq2Rs3Tu4Vw5X" diff --git a/tests/unit/enterprise/proxy/auth/test_user_api_key_auth.py b/tests/unit/enterprise/proxy/auth/test_user_api_key_auth.py index fd674afd85a..d21bb046549 100644 --- a/tests/unit/enterprise/proxy/auth/test_user_api_key_auth.py +++ b/tests/unit/enterprise/proxy/auth/test_user_api_key_auth.py @@ -5,6 +5,7 @@ from fastapi import Request from litellm_enterprise.proxy.auth.user_api_key_auth import enterprise_custom_auth from litellm.proxy._types import UserAPIKeyAuth +from tests._master_key import MASTER_KEY @pytest.mark.asyncio @@ -56,7 +57,7 @@ async def test_enterprise_custom_auth_returns_string(): "litellm.proxy.auth.user_api_key_auth.enterprise_custom_auth", mock_user_auth, ), - patch("litellm.proxy.proxy_server.master_key", "sk-1234"), + patch("litellm.proxy.proxy_server.master_key", MASTER_KEY), patch("litellm.proxy.proxy_server.prisma_client", MagicMock()), ): # Verify the key is correctly handled in _user_api_key_auth_builder diff --git a/tests/unit/enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py b/tests/unit/enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py index 226755e7b8e..052300ed2d2 100644 --- a/tests/unit/enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py +++ b/tests/unit/enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py @@ -39,6 +39,7 @@ from litellm.proxy._types import ( UserAPIKeyAuth, ProxyException, ) +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -80,7 +81,7 @@ async def test_new_project(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -93,7 +94,7 @@ async def test_new_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -115,7 +116,7 @@ async def test_new_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -152,7 +153,7 @@ async def test_update_project(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -165,7 +166,7 @@ async def test_update_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -187,7 +188,7 @@ async def test_update_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -215,7 +216,7 @@ async def test_update_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -257,7 +258,7 @@ async def test_delete_project(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -270,7 +271,7 @@ async def test_delete_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -288,7 +289,7 @@ async def test_delete_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -304,7 +305,7 @@ async def test_delete_project(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -322,7 +323,7 @@ async def test_delete_project(prisma_client): project_id=project_id, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -347,7 +348,7 @@ async def test_project_info(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() @@ -360,7 +361,7 @@ async def test_project_info(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -382,7 +383,7 @@ async def test_project_info(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -395,7 +396,7 @@ async def test_project_info(prisma_client): project_id=project_id, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -840,7 +841,7 @@ async def test_list_projects_returns_timestamps(): response = await list_projects( user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -911,7 +912,7 @@ async def test_update_project_invalidates_cached_project_object(monkeypatch): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -961,7 +962,7 @@ async def test_delete_project_invalidates_cached_project_object(monkeypatch): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1005,7 +1006,7 @@ async def test_update_project_succeeds_when_cache_eviction_fails(monkeypatch): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1206,7 +1207,7 @@ async def _run_new_project(data: NewProjectRequest) -> None: await new_project( data=data, http_request=Request(scope={"type": "http"}), - user_api_key_dict=UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="1234"), + user_api_key_dict=UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="1234"), ) @@ -1243,7 +1244,7 @@ async def _run_project_update(project_id: str, **fields) -> None: http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) diff --git a/tests/unit/integrations/langfuse/test_langfuse_prompt_management.py b/tests/unit/integrations/langfuse/test_langfuse_prompt_management.py index a7a553b2d9f..b487fe88b06 100644 --- a/tests/unit/integrations/langfuse/test_langfuse_prompt_management.py +++ b/tests/unit/integrations/langfuse/test_langfuse_prompt_management.py @@ -75,7 +75,7 @@ class TestLangfusePromptManagement: with ( patch( "litellm.integrations.langfuse.langfuse_prompt_management.resolve_langfuse_credentials", - return_value=("pk-1234", "sk-1234", "https://localhost"), + return_value=("pk-1234", "sk-9876", "https://localhost"), ), patch( "litellm.integrations.langfuse.langfuse_sdk.build_langfuse_client", built @@ -87,7 +87,7 @@ class TestLangfusePromptManagement: ): langfuse_client_init( langfuse_public_key="pk-1234", - langfuse_secret="sk-1234", + langfuse_secret="sk-9876", langfuse_host="https://localhost", ) diff --git a/tests/unit/integrations/websearch_interception/test_websearch_interception_handler.py b/tests/unit/integrations/websearch_interception/test_websearch_interception_handler.py index a5ab28ba72a..b6a7c2ccb93 100644 --- a/tests/unit/integrations/websearch_interception/test_websearch_interception_handler.py +++ b/tests/unit/integrations/websearch_interception/test_websearch_interception_handler.py @@ -287,7 +287,7 @@ async def test_execute_search_attributes_spend_to_the_calling_key(monkeypatch): ] mock_asearch = AsyncMock(return_value=SearchResponse(object="search", results=[])) user_api_key_auth = UserAPIKeyAuth( - api_key="hashed-sk-1234", + api_key="hashed-sk-9876", key_alias="alice-key", user_id="user-alice", org_id="org-1", @@ -302,8 +302,8 @@ async def test_execute_search_attributes_spend_to_the_calling_key(monkeypatch): ) forwarded_metadata = mock_asearch.await_args.kwargs["litellm_metadata"] - assert forwarded_metadata["user_api_key"] == "hashed-sk-1234" - assert forwarded_metadata["user_api_key_hash"] == "hashed-sk-1234" + assert forwarded_metadata["user_api_key"] == "hashed-sk-9876" + assert forwarded_metadata["user_api_key_hash"] == "hashed-sk-9876" assert forwarded_metadata["user_api_key_alias"] == "alice-key" assert forwarded_metadata["user_api_key_user_id"] == "user-alice" assert forwarded_metadata["user_api_key_org_id"] == "org-1" @@ -341,7 +341,7 @@ def _perplexity_router() -> MagicMock: "litellm_trace_id": "trace-abc", "litellm_session_id": "session-abc", "metadata": { - "user_api_key_auth": UserAPIKeyAuth(api_key="hashed-sk-1234"), + "user_api_key_auth": UserAPIKeyAuth(api_key="hashed-sk-9876"), "session_id": "session-abc", }, }, @@ -351,7 +351,7 @@ def _perplexity_router() -> MagicMock: { "litellm_call_id": "parent-call-1", "litellm_metadata": { - "user_api_key_auth": UserAPIKeyAuth(api_key="hashed-sk-1234"), + "user_api_key_auth": UserAPIKeyAuth(api_key="hashed-sk-9876"), "session_id": "session-abc", "trace_id": "trace-abc", }, @@ -363,7 +363,7 @@ def _perplexity_router() -> MagicMock: "litellm_params": { "litellm_call_id": "parent-call-1", "litellm_trace_id": "trace-abc", - "metadata": {"user_api_key_auth": UserAPIKeyAuth(api_key="hashed-sk-1234")}, + "metadata": {"user_api_key_auth": UserAPIKeyAuth(api_key="hashed-sk-9876")}, "litellm_metadata": {"session_id": "session-abc"}, } }, @@ -393,7 +393,7 @@ async def test_execute_search_inherits_parent_request_session_and_trace( assert forwarded["litellm_metadata"]["session_id"] == "session-abc" assert forwarded["litellm_metadata"]["trace_id"] == "trace-abc" assert forwarded["litellm_metadata"]["parent_request_id"] == "parent-call-1" - assert forwarded["litellm_metadata"]["user_api_key"] == "hashed-sk-1234" + assert forwarded["litellm_metadata"]["user_api_key"] == "hashed-sk-9876" assert forwarded["litellm_metadata"]["model_group"] == "perplexity-sonar-pro" assert "litellm_call_id" not in forwarded assert ( diff --git a/tests/unit/litellm_core_utils/test_sensitive_data_masker.py b/tests/unit/litellm_core_utils/test_sensitive_data_masker.py index fcdf7fb4798..5f73f3863e6 100644 --- a/tests/unit/litellm_core_utils/test_sensitive_data_masker.py +++ b/tests/unit/litellm_core_utils/test_sensitive_data_masker.py @@ -35,7 +35,7 @@ def test_excluded_keys_exact_match(): masker = SensitiveDataMasker() data = { - "api_key": "sk-1234567890abcdef", + "api_key": "sk-9876567890abcdef", "litellm_credentials_name": "my-credential-name", "access_token": "token-12345", "port": 6379, @@ -43,7 +43,7 @@ def test_excluded_keys_exact_match(): # Without excluded_keys, sensitive keys should be masked masked = masker.mask_dict(data) - assert masked["api_key"] != "sk-1234567890abcdef" + assert masked["api_key"] != "sk-9876567890abcdef" assert "*" in masked["api_key"] assert masked["access_token"] != "token-12345" assert "*" in masked["access_token"] @@ -54,7 +54,7 @@ def test_excluded_keys_exact_match(): assert masked["litellm_credentials_name"] == "my-credential-name" # Other sensitive keys should still be masked - assert masked["api_key"] != "sk-1234567890abcdef" + assert masked["api_key"] != "sk-9876567890abcdef" assert "*" in masked["api_key"] assert masked["access_token"] != "token-12345" assert "*" in masked["access_token"] @@ -72,7 +72,7 @@ def test_excluded_keys_exact_match(): # Test with api_key in excluded_keys to verify it works for keys that would be masked masked = masker.mask_dict(data, excluded_keys={"api_key"}) - assert masked["api_key"] == "sk-1234567890abcdef" # Should NOT be masked + assert masked["api_key"] == "sk-9876567890abcdef" # Should NOT be masked assert masked["access_token"] != "token-12345" # Should still be masked assert "*" in masked["access_token"] @@ -108,13 +108,13 @@ def test_lists_with_sensitive_keys_are_masked(): """ masker = SensitiveDataMasker() data = { - "api_key": ["sk-1234567890abcdef", "sk-9876543210fedcba"], + "api_key": ["sk-9876567890abcdef", "sk-9876543210fedcba"], "tags": ["prod", "test"], } masked = masker.mask_dict(data) # sensitive key list entries should be masked - assert masked["api_key"][0] != "sk-1234567890abcdef" + assert masked["api_key"][0] != "sk-9876567890abcdef" assert "*" in masked["api_key"][0] assert masked["api_key"][1] != "sk-9876543210fedcba" assert "*" in masked["api_key"][1] @@ -177,7 +177,7 @@ def test_cost_per_token_fields_not_masked(): "cache_read_input_token_cost": 9.0e-07, "cache_creation_input_token_cost": 3.75e-06, # Real secret fields should still be masked - "api_key": "sk-1234567890abcdef", + "api_key": "sk-9876567890abcdef", "access_token": "my-secret-token", } diff --git a/tests/unit/llms/anthropic/test_anthropic_common_utils.py b/tests/unit/llms/anthropic/test_anthropic_common_utils.py index 8b9729fa9f0..054cd8fd742 100644 --- a/tests/unit/llms/anthropic/test_anthropic_common_utils.py +++ b/tests/unit/llms/anthropic/test_anthropic_common_utils.py @@ -776,7 +776,7 @@ class TestProxyOAuthHeaderForwarding: ): """Authorization Bearer (LiteLLM key) must never be forwarded to the LLM provider. - When a user sends their LiteLLM key as 'Authorization: Bearer sk-1234' and + When a user sends their LiteLLM key as 'Authorization: Bearer sk-9876' and forward_llm_provider_auth_headers=True, the Authorization header must be stripped — not sent to Anthropic as if it were an Anthropic API key. """ @@ -786,7 +786,7 @@ class TestProxyOAuthHeaderForwarding: raw_headers = Headers( raw=[ - (b"authorization", b"Bearer sk-1234-litellm-proxy-key"), + (b"authorization", b"Bearer sk-9876-litellm-proxy-key"), (b"x-api-key", b"sk-ant-api03-real-anthropic-key"), (b"content-type", b"application/json"), ] diff --git a/tests/unit/llms/pg_vector/vector_stores/test_pg_vector_transformation.py b/tests/unit/llms/pg_vector/vector_stores/test_pg_vector_transformation.py index 1d44b2bc278..3d84ece983a 100644 --- a/tests/unit/llms/pg_vector/vector_stores/test_pg_vector_transformation.py +++ b/tests/unit/llms/pg_vector/vector_stores/test_pg_vector_transformation.py @@ -237,7 +237,7 @@ class TestPGVectorStoreConfig: # Test parameters - use a different vector store ID than test registry api_base = "http://localhost:8001" - api_key = "sk-1234" + api_key = "sk-9876" vector_store_id = ( "pg-vector-test-store-123" # Different from test registry IDs ) diff --git a/tests/unit/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py b/tests/unit/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py index 02ac1540071..35004c8b787 100644 --- a/tests/unit/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py +++ b/tests/unit/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py @@ -2810,7 +2810,7 @@ class TestMCPDelegateAuthToUpstream: "type": "http", "method": "POST", "path": "/mcp/delegated_oauth_server", - "headers": [(b"x-litellm-api-key", b"Bearer sk-1234")], + "headers": [(b"x-litellm-api-key", b"Bearer sk-9876")], } with ( @@ -2842,7 +2842,7 @@ class TestMCPDelegateAuthToUpstream: "type": "http", "method": "POST", "path": "/mcp/delegated_oauth_server", - "headers": [(b"authorization", b"Bearer sk-1234")], + "headers": [(b"authorization", b"Bearer sk-9876")], } with ( @@ -2867,7 +2867,7 @@ class TestMCPDelegateAuthToUpstream: ) = await MCPRequestHandler.process_mcp_request(scope) assert isinstance(auth_result, UserAPIKeyAuth) assert auth_result.user_id == "real-user" - assert oauth2_headers.get("Authorization") == "Bearer sk-1234" + assert oauth2_headers.get("Authorization") == "Bearer sk-9876" mock_auth.assert_awaited_once() async def test_delegate_ignored_for_client_credentials_server(self): diff --git a/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_credentials.py b/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_credentials.py index 992b1e8632b..a49c43bedb5 100644 --- a/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_credentials.py +++ b/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_credentials.py @@ -80,8 +80,8 @@ def test_kdf_differs_across_master_keys(): @pytest.mark.parametrize( "value,expected", [ - ("Bearer sk-1234", False), - ("sk-1234", False), + ("Bearer sk-9876", False), + ("sk-9876", False), ("Bearer llm_env_abc", False), ("Bearer llm_refresh_abc", False), ("llm_session_abc", True), @@ -102,7 +102,7 @@ def test_resolve_admits_valid_access_token_with_and_without_scheme(): def test_resolve_passes_non_session_bearers_through(): - for value in ("Bearer sk-1234", "Bearer llm_env_whatever", "Bearer eyJhbGciOi"): + for value in ("Bearer sk-9876", "Bearer llm_env_whatever", "Bearer eyJhbGciOi"): assert isinstance(resolve_session_bearer(value, KEYS, NOW), NotSessionBearer) diff --git a/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_token.py b/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_token.py index 321d6d0a1d2..bc7ec1e1112 100644 --- a/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_token.py +++ b/tests/unit/proxy/_experimental/mcp_server/outbound_credentials/test_session_token.py @@ -156,7 +156,7 @@ def test_key_rotation_invalidates_outstanding_tokens(): @pytest.mark.parametrize( "candidate,expected", [ - ("sk-1234", NotASessionToken), + ("sk-9876", NotASessionToken), ("llm_env_something", NotASessionToken), ("", NotASessionToken), (SESSION_TOKEN_PREFIX, SessionMalformed), diff --git a/tests/unit/proxy/_experimental/mcp_server/test_mcp_debug.py b/tests/unit/proxy/_experimental/mcp_server/test_mcp_debug.py index 46ecd4df716..ed1ae0bb4fe 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_mcp_debug.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_mcp_debug.py @@ -51,10 +51,10 @@ class TestMask: def test_short_value_masked(self): # Short auth values must not be echoed verbatim in debug headers, even though # visible_prefix + visible_suffix would otherwise reveal the whole value. - masked = MCPDebug._mask("sk-1234") - assert "sk-1234" not in masked + masked = MCPDebug._mask("sk-9876") + assert "sk-9876" not in masked assert set(masked) == {"*"} - assert len(masked) == len("sk-1234") + assert len(masked) == len("sk-9876") def test_long_value_masked(self): result = MCPDebug._mask("Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9") @@ -63,9 +63,9 @@ class TestMask: assert "****" in result or "**" in result def test_litellm_key_masked(self): - result = MCPDebug._mask("Bearer sk-1234567890abcdef") + result = MCPDebug._mask("Bearer sk-9876567890abcdef") assert result.startswith("Bearer") - assert "sk-1234567890abcdef" not in result + assert "sk-9876567890abcdef" not in result class TestBuildDebugHeaders: @@ -87,11 +87,11 @@ class TestBuildDebugHeaders: def test_litellm_key_in_dedicated_header(self): headers = MCPDebug.build_debug_headers( inbound_headers={ - "x-litellm-api-key": "Bearer sk-1234567890abcdef", + "x-litellm-api-key": "Bearer sk-9876567890abcdef", "host": "localhost", }, oauth2_headers=None, - litellm_api_key="Bearer sk-1234567890abcdef", + litellm_api_key="Bearer sk-9876567890abcdef", auth_resolution="no-auth", server_url="https://mcp.example.com", server_auth_type="oauth2", @@ -103,10 +103,10 @@ class TestBuildDebugHeaders: """When Authorization and x-litellm-api-key carry the same token.""" headers = MCPDebug.build_debug_headers( inbound_headers={ - "authorization": "Bearer sk-1234567890abcdef", + "authorization": "Bearer sk-9876567890abcdef", }, - oauth2_headers={"Authorization": "Bearer sk-1234567890abcdef"}, - litellm_api_key="Bearer sk-1234567890abcdef", + oauth2_headers={"Authorization": "Bearer sk-9876567890abcdef"}, + litellm_api_key="Bearer sk-9876567890abcdef", auth_resolution="oauth2-passthrough", server_url="https://mcp.example.com", server_auth_type="oauth2", diff --git a/tests/unit/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py b/tests/unit/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py index d39ec063538..333984bde68 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_mcp_hook_extra_headers.py @@ -885,8 +885,8 @@ class TestHookHeaderMergePriority: tasks=[], mcp_auth_header=None, mcp_server_auth_headers=None, - oauth2_headers={"Authorization": "Bearer sk-1234"}, - raw_headers={"authorization": "Bearer sk-1234"}, + oauth2_headers={"Authorization": "Bearer sk-9876"}, + raw_headers={"authorization": "Bearer sk-9876"}, proxy_logging_obj=None, hook_extra_headers=None, ) @@ -929,9 +929,9 @@ class TestHookHeaderMergePriority: tasks=[], mcp_auth_header=None, mcp_server_auth_headers=None, - oauth2_headers={"Authorization": "Bearer sk-1234"}, + oauth2_headers={"Authorization": "Bearer sk-9876"}, raw_headers={ - "authorization": "Bearer sk-1234", + "authorization": "Bearer sk-9876", "x-custom": "from-client", }, proxy_logging_obj=None, diff --git a/tests/unit/proxy/_experimental/mcp_server/test_mcp_partial_update.py b/tests/unit/proxy/_experimental/mcp_server/test_mcp_partial_update.py index 122b22f6273..d6894979906 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_mcp_partial_update.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_mcp_partial_update.py @@ -522,7 +522,7 @@ async def test_create_still_writes_defaults(): @pytest.fixture(autouse=True) def _salt_key(monkeypatch): - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", "sk-9876") def _existing_row(auth_type: str, credentials: dict | None = None): diff --git a/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_manager.py b/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_manager.py index 123a5505953..8daec99e7ad 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_manager.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_manager.py @@ -3854,7 +3854,7 @@ class TestMCPServerManager: _should_strip_caller_authorization( mcp_server=oauth_delegate, raw_headers={ - "x-litellm-api-key": "Bearer sk-1234", + "x-litellm-api-key": "Bearer sk-9876", "authorization": "Bearer upstream", }, user_api_key_auth=UserAPIKeyAuth(user_id="alice", api_key=None), diff --git a/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_tool_calls_and_headers.py b/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_tool_calls_and_headers.py index 3b53d023af3..7b9fddebb36 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_tool_calls_and_headers.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_mcp_server_tool_calls_and_headers.py @@ -669,9 +669,9 @@ def test_prepare_mcp_server_headers_m2m_skips_authorization_from_raw_extra_heade server=server, mcp_server_auth_headers=None, mcp_auth_header=None, - oauth2_headers={"Authorization": "Bearer sk-1234"}, + oauth2_headers={"Authorization": "Bearer sk-9876"}, raw_headers={ - "authorization": "Bearer sk-1234", + "authorization": "Bearer sk-9876", "x-custom": "trace", }, ) @@ -833,8 +833,8 @@ async def test_call_tool_m2m_skips_authorization_headers(): tasks=[], mcp_auth_header=None, mcp_server_auth_headers=None, - oauth2_headers={"Authorization": "Bearer sk-1234"}, - raw_headers={"authorization": "Bearer sk-1234", "x-custom": "trace"}, + oauth2_headers={"Authorization": "Bearer sk-9876"}, + raw_headers={"authorization": "Bearer sk-9876", "x-custom": "trace"}, proxy_logging_obj=None, ) @@ -6696,7 +6696,7 @@ async def test_list_tools_with_legacy_db_m2m_server_resolves_oauth2_flow(): except ImportError: pytest.skip("MCP server not available") - user_auth = UserAPIKeyAuth(api_key="sk-1234", user_id="test-user") + user_auth = UserAPIKeyAuth(api_key="sk-9876", user_id="test-user") # Simulate a legacy DB row: OAuth2 with M2M credentials but oauth2_flow=None legacy_server = MagicMock(name="legacy_m2m_server") @@ -6769,7 +6769,7 @@ async def test_list_tools_with_legacy_db_m2m_server_resolves_oauth2_flow(): mcp_auth_header=None, mcp_servers=["legacy_m2m"], mcp_server_auth_headers=None, - oauth2_headers={"Authorization": "Bearer sk-1234"}, # Caller's token + oauth2_headers={"Authorization": "Bearer sk-9876"}, # Caller's token ) # With P1 fix: _get_allowed_mcp_servers applies _resolve_oauth2_flow, @@ -6815,7 +6815,7 @@ async def test_call_tool_empty_extra_headers_returns_none(): ) raw_headers = { - "Authorization": "Bearer sk-1234", + "Authorization": "Bearer sk-9876", "Content-Type": "application/json", } @@ -9497,7 +9497,7 @@ async def test_call_tool_with_legacy_db_m2m_server_resolves_oauth2_flow(): except ImportError: pytest.skip("MCP server not available") - user_auth = UserAPIKeyAuth(api_key="sk-1234", user_id="test-user") + user_auth = UserAPIKeyAuth(api_key="sk-9876", user_id="test-user") legacy_server = MCPServer( server_id="legacy-m2m-id", diff --git a/tests/unit/proxy/_experimental/mcp_server/test_mcp_stale_session.py b/tests/unit/proxy/_experimental/mcp_server/test_mcp_stale_session.py index eb1d8573ee3..bf1f0f97a18 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_mcp_stale_session.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_mcp_stale_session.py @@ -1357,7 +1357,7 @@ async def test_handle_streamable_http_mcp_oauth_delegate_with_forwarded_token_sk scope = _passthrough_mode_scope( "od_server", extra_headers=[ - (b"x-litellm-api-key", b"Bearer sk-1234"), + (b"x-litellm-api-key", b"Bearer sk-9876"), (b"authorization", b"Bearer upstream-token"), ], ) diff --git a/tests/unit/proxy/_experimental/mcp_server/test_rest_endpoints.py b/tests/unit/proxy/_experimental/mcp_server/test_rest_endpoints.py index 20a8ee05eb5..bd3c34f5abf 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_rest_endpoints.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_rest_endpoints.py @@ -4501,7 +4501,7 @@ class TestV1ResolvedOauth2Gate: headers = await rest_endpoints._get_user_oauth_extra_headers( server, - UserAPIKeyAuth(user_id="alice", api_key="sk-1234"), + UserAPIKeyAuth(user_id="alice", api_key="sk-9876"), prefetched_creds={"oauth2-srv": {"access_token": "stored-token"}}, ) diff --git a/tests/unit/proxy/anthropic_endpoints/test_claude_code_marketplace.py b/tests/unit/proxy/anthropic_endpoints/test_claude_code_marketplace.py index a585666743f..b4780bfefeb 100644 --- a/tests/unit/proxy/anthropic_endpoints/test_claude_code_marketplace.py +++ b/tests/unit/proxy/anthropic_endpoints/test_claude_code_marketplace.py @@ -28,6 +28,7 @@ from litellm.proxy.anthropic_endpoints.claude_code_endpoints.claude_code_marketp register_plugin, update_plugin, ) +from tests._master_key import MASTER_KEY def _make_mock_prisma(): @@ -80,7 +81,7 @@ def _make_mock_prisma(): _USER = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test-user", ) @@ -107,7 +108,7 @@ _ARCHIVE_SOURCE = { def _patch_proxy_globals(monkeypatch): """Scope prisma_client/master_key mutations to each test via monkeypatch.""" monkeypatch.setattr(litellm.proxy.proxy_server, "prisma_client", _make_mock_prisma()) - monkeypatch.setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + monkeypatch.setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) @pytest.mark.asyncio diff --git a/tests/unit/proxy/anthropic_endpoints/test_claude_code_skill_access.py b/tests/unit/proxy/anthropic_endpoints/test_claude_code_skill_access.py index dc4016d6db0..3e21ac9c796 100644 --- a/tests/unit/proxy/anthropic_endpoints/test_claude_code_skill_access.py +++ b/tests/unit/proxy/anthropic_endpoints/test_claude_code_skill_access.py @@ -58,7 +58,7 @@ def test_visibility_enabled_plugin_is_public_for_everyone(): def test_visibility_disabled_plugin_needs_grant_or_admin(): private = _plugin("private-skill", enabled=False) - admin = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + admin = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) assert not skill_visibility(None).allows(private) assert not skill_visibility(_key(None, None)).allows(private) @@ -70,7 +70,7 @@ def test_visibility_disabled_plugin_needs_grant_or_admin(): def test_where_clause_bounds_the_plugin_query_to_what_the_caller_may_see(): - admin = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + admin = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) assert skill_visibility(None).where() == {"enabled": True} assert skill_visibility(_key(None, None)).where() == {"enabled": True} diff --git a/tests/unit/proxy/auth/test_auth_checks_object_access_and_lookup.py b/tests/unit/proxy/auth/test_auth_checks_object_access_and_lookup.py index 63832c485f9..9ce23c442f6 100644 --- a/tests/unit/proxy/auth/test_auth_checks_object_access_and_lookup.py +++ b/tests/unit/proxy/auth/test_auth_checks_object_access_and_lookup.py @@ -95,6 +95,7 @@ from litellm.proxy.common_utils.user_api_key_cache import ( ) from litellm.utils import get_utc_datetime from litellm.vector_stores.vector_store_registry import VectorStoreRegistry +from tests._master_key import MASTER_KEY def _rendered_log_message(call): @@ -106,7 +107,7 @@ def _rendered_log_message(call): @pytest.fixture(autouse=True) def set_salt_key(monkeypatch): """Automatically set LITELLM_SALT_KEY for all tests""" - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", MASTER_KEY) @pytest.fixture diff --git a/tests/unit/proxy/auth/test_auth_utils.py b/tests/unit/proxy/auth/test_auth_utils.py index 90e0595dc17..8559d07b5ee 100644 --- a/tests/unit/proxy/auth/test_auth_utils.py +++ b/tests/unit/proxy/auth/test_auth_utils.py @@ -1507,8 +1507,8 @@ def test_abbreviate_api_key(): def test_abbreviate_api_key_short_key_is_fully_masked(): """Regression test for LIT-4355: for keys shorter than the enforced minimum, - showing the last 4 characters can reveal the entire key (sk-1234 -> sk-...1234).""" - assert abbreviate_api_key("sk-1234") == "sk-..." + showing the last 4 characters can reveal the entire key (sk-9876 -> sk-...1234).""" + assert abbreviate_api_key("sk-9876") == "sk-..." assert abbreviate_api_key("sk-test-1234") == "sk-..." assert abbreviate_api_key("") == "sk-..." diff --git a/tests/unit/proxy/auth/test_jwt.py b/tests/unit/proxy/auth/test_jwt.py index fd1d8974b48..a7aa379ad37 100644 --- a/tests/unit/proxy/auth/test_jwt.py +++ b/tests/unit/proxy/auth/test_jwt.py @@ -1289,7 +1289,7 @@ def test_user_api_key_auth_jwt_hashing(): assert jwt_token not in user_auth.token # Test with a regular API key (should not be hashed) - regular_api_key = "sk-1234567890abcdef" + regular_api_key = "sk-9876567890abcdef" user_auth_regular = UserAPIKeyAuth(api_key=regular_api_key) # Verify that regular API key is hashed normally (without "hashed-jwt-" prefix) @@ -1320,7 +1320,7 @@ def test_jwt_handler_is_jwt_static_method(): assert JWTHandler.is_jwt(invalid_jwt) == False # Test with regular API key - regular_key = "sk-1234567890abcdef" + regular_key = "sk-9876567890abcdef" assert JWTHandler.is_jwt(regular_key) == False # Test with empty string diff --git a/tests/unit/proxy/auth/test_login_utils.py b/tests/unit/proxy/auth/test_login_utils.py index 28ca47d01de..e095af20b9c 100644 --- a/tests/unit/proxy/auth/test_login_utils.py +++ b/tests/unit/proxy/auth/test_login_utils.py @@ -53,6 +53,7 @@ from litellm.proxy.auth.login_utils import ( is_env_credential_login_enabled, screen_login_password_for_breach, ) +from tests._master_key import MASTER_KEY # Successful DB-user logins schedule the background HIBP screen; disable it so # no test ever does live network I/O to haveibeenpwned.com from CI. @@ -94,9 +95,9 @@ def test_get_ui_credentials_requires_password(): @pytest.mark.asyncio async def test_authenticate_user_admin_login_with_ui_credentials(): """Test admin login using UI_USERNAME and UI_PASSWORD""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" - ui_password = "sk-1234" + ui_password = MASTER_KEY mock_prisma_client = MagicMock() mock_prisma_client.db.litellm_usertable.find_first = AsyncMock(return_value=None) @@ -146,7 +147,7 @@ async def test_authenticate_user_admin_login_with_ui_credentials(): @pytest.mark.asyncio async def test_authenticate_user_admin_login_with_master_key_as_password(monkeypatch): """Test admin login when UI_PASSWORD is not set, should use master_key""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" mock_prisma_client = MagicMock() @@ -201,7 +202,7 @@ async def test_authenticate_user_admin_login_with_master_key_as_password(monkeyp @pytest.mark.asyncio async def test_authenticate_user_invalid_credentials(): """Test authentication failure with invalid credentials""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" wrong_password = "wrong-password" @@ -246,7 +247,7 @@ async def test_authenticate_user_missing_master_key(): @pytest.mark.asyncio async def test_authenticate_user_wrong_password(): """Test authentication failure with wrong password for database user""" - master_key = "sk-1234" + master_key = MASTER_KEY user_email = "test@example.com" correct_password = "correct-password" wrong_password = "wrong-password" @@ -287,7 +288,7 @@ async def test_authenticate_user_wrong_password(): @pytest.mark.asyncio async def test_authenticate_user_email_case_insensitive_login(): """Test that email lookup is case-insensitive during login""" - master_key = "sk-1234" + master_key = MASTER_KEY stored_email = "testemail@test.com" login_email_mixed_case = "testEmail@test.com" correct_password = "correct-password" @@ -361,9 +362,9 @@ async def test_authenticate_user_email_case_insensitive_login(): @pytest.mark.asyncio async def test_authenticate_user_database_required_for_admin(monkeypatch): """Test that database is required for admin login""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" - ui_password = "sk-1234" + ui_password = MASTER_KEY mock_prisma_client = MagicMock() mock_prisma_client.db.litellm_usertable.find_first = AsyncMock(return_value=None) @@ -400,9 +401,9 @@ async def test_authenticate_user_database_required_for_admin(monkeypatch): @pytest.mark.asyncio async def test_authenticate_user_admin_login_with_non_ascii_characters(): """Test admin login with non-ASCII characters in password (issue #19559)""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin£test" - ui_password = "sk-1234£pass" + ui_password = "sk-9876£pass" mock_prisma_client = MagicMock() mock_prisma_client.db.litellm_usertable.find_first = AsyncMock(return_value=None) @@ -474,9 +475,9 @@ async def test_authenticate_user_multiple_logins_generate_unique_tokens(): This test verifies that users can have multiple concurrent UI sessions. Previous UI session tokens should NOT be expired/blocked when a new session is created. """ - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" - ui_password = "sk-1234" + ui_password = MASTER_KEY mock_prisma_client = MagicMock() mock_prisma_client.db.litellm_usertable.find_first = AsyncMock(return_value=None) @@ -547,7 +548,7 @@ async def test_authenticate_user_multiple_logins_generate_unique_tokens(): @pytest.mark.asyncio async def test_authenticate_user_database_login_with_non_ascii_password(): """Test database user login with non-ASCII characters in password (issue #19559)""" - master_key = "sk-1234" + master_key = MASTER_KEY user_email = "test@example.com" password_with_special_char = "correct£password" hashed_password = hash_token(token=password_with_special_char) @@ -1764,7 +1765,7 @@ class TestDisablePasswordLoginWhenSSOEnabled: @pytest.mark.asyncio async def test_rejects_correct_admin_credentials_when_sso_configured(self): - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" mock_prisma_client = MagicMock() @@ -1790,7 +1791,7 @@ class TestDisablePasswordLoginWhenSSOEnabled: @pytest.mark.asyncio async def test_rejects_correct_db_user_credentials_when_sso_configured(self): - master_key = "sk-1234" + master_key = MASTER_KEY user_email = "test@example.com" password = "correct-password" @@ -1823,7 +1824,7 @@ class TestDisablePasswordLoginWhenSSOEnabled: async def test_allows_password_login_when_setting_enabled_but_sso_not_configured(self): """The setting alone must not lock out an admin who has not actually configured SSO — there would be no fallback left.""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" mock_prisma_client = MagicMock() @@ -1860,7 +1861,7 @@ class TestDisablePasswordLoginWhenSSOEnabled: fail. The gate must read the real env (no is_sso_provider_fully_configured mock here) and still let password login through, or an admin who set one env var by mistake is locked out with no way in.""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" mock_prisma_client = MagicMock() @@ -1894,7 +1895,7 @@ class TestDisablePasswordLoginWhenSSOEnabled: async def test_allows_password_login_when_sso_configured_but_setting_not_enabled(self): """SSO being configured must not, by itself, disable the password fallback: the setting is opt-in.""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" mock_prisma_client = MagicMock() @@ -1933,7 +1934,7 @@ class TestDisableEnvCredentialLogin: @pytest.mark.asyncio async def test_rejects_correct_env_credentials_when_disabled(self): - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" ui_password = "env-only-password" @@ -1960,7 +1961,7 @@ class TestDisableEnvCredentialLogin: async def test_rejects_master_key_fallback_when_disabled(self): """With UI_PASSWORD unset, the master key IS the env password, so the setting must reject it too or it protects nothing by default.""" - master_key = "sk-1234" + master_key = MASTER_KEY mock_prisma_client = MagicMock() mock_prisma_client.db.litellm_usertable.find_first = AsyncMock(return_value=None) @@ -1981,7 +1982,7 @@ class TestDisableEnvCredentialLogin: @pytest.mark.asyncio @respx.mock async def test_db_user_login_still_works_when_disabled(self, httpx_transport): - master_key = "sk-1234" + master_key = MASTER_KEY user_email = "admin@example.com" password = "Str0ng!Passw0rd" sha1 = hashlib.sha1(password.encode("utf-8"), usedforsecurity=False).hexdigest().upper() @@ -2032,7 +2033,7 @@ class TestDisableEnvCredentialLogin: async def test_env_login_still_works_when_setting_absent(self): """Env-credential login is the bootstrap path on a fresh install and must stay on by default.""" - master_key = "sk-1234" + master_key = MASTER_KEY ui_username = "admin" mock_prisma_client = MagicMock() @@ -2131,7 +2132,7 @@ class TestPasswordResetRequiredSessionMinting: result = await authenticate_user( username="reset@example.com", password="Str0ng!Passw0rd", - master_key="sk-1234", + master_key=MASTER_KEY, prisma_client=mock_prisma_client, throttle=_unlimited_throttle(), general_settings=_POLICY_NO_BREACH_CHECK, @@ -2173,7 +2174,7 @@ class TestPasswordResetRequiredSessionMinting: result = await authenticate_user( username="reset@example.com", password="Str0ng!Passw0rd", - master_key="sk-1234", + master_key=MASTER_KEY, prisma_client=mock_prisma_client, throttle=_unlimited_throttle(), general_settings=_POLICY_NO_BREACH_CHECK, diff --git a/tests/unit/proxy/auth/test_master_key_boot_check.py b/tests/unit/proxy/auth/test_master_key_boot_check.py index aca65f4c7e6..dc490068c4d 100644 --- a/tests/unit/proxy/auth/test_master_key_boot_check.py +++ b/tests/unit/proxy/auth/test_master_key_boot_check.py @@ -5,6 +5,7 @@ import subprocess import sys from collections.abc import Mapping from pathlib import Path +from typing import Final import pytest @@ -32,6 +33,8 @@ from litellm.proxy.auth.master_key_boot_check import ( with_stored_secrets_counted, ) +PUBLICLY_KNOWN_KEY: Final = "sk-" + "1234" + def _verdict( master_key: str | None, @@ -60,8 +63,8 @@ def _verdict( (None, UnsafeMasterKeyReason.NOT_SET), ("", UnsafeMasterKeyReason.EMPTY), (" \t\n", UnsafeMasterKeyReason.EMPTY), - ("sk-1234", UnsafeMasterKeyReason.PUBLICLY_KNOWN), - (" sk-1234\n", UnsafeMasterKeyReason.PUBLICLY_KNOWN), + (PUBLICLY_KNOWN_KEY, UnsafeMasterKeyReason.PUBLICLY_KNOWN), + (" " + PUBLICLY_KNOWN_KEY + "\n", UnsafeMasterKeyReason.PUBLICLY_KNOWN), ], ) def test_unsafe_master_keys_are_refused_with_their_reason(master_key: str | None, reason: UnsafeMasterKeyReason): @@ -71,12 +74,15 @@ def test_unsafe_master_keys_are_refused_with_their_reason(master_key: str | None assert verdict.reason is reason -@pytest.mark.parametrize("master_key", ["sk-12345", "sk-1234567890", "1234", "sk-qa-9f2c1e7a44b0d3"]) +@pytest.mark.parametrize( + "master_key", + [PUBLICLY_KNOWN_KEY + "5", PUBLICLY_KNOWN_KEY + "567890", "1234", "sk-qa-9f2c1e7a44b0d3"], +) def test_keys_that_only_resemble_the_known_default_are_safe(master_key: str): assert _verdict(master_key) == SafeMasterKey() -@pytest.mark.parametrize("master_key", [None, "", "sk-1234"]) +@pytest.mark.parametrize("master_key", [None, "", PUBLICLY_KNOWN_KEY]) def test_either_override_lets_an_unsafe_key_through(master_key: str | None): from_env = _verdict(master_key, override_env_is_on=True) from_yaml = _verdict(master_key, {WEAK_OR_UNSET_MASTER_KEY_OVERRIDE_SETTING: True}) @@ -86,7 +92,9 @@ def test_either_override_lets_an_unsafe_key_through(master_key: str | None): def test_override_switched_off_in_yaml_still_refuses(): - assert isinstance(_verdict("sk-1234", {WEAK_OR_UNSET_MASTER_KEY_OVERRIDE_SETTING: False}), UnsafeMasterKeyRefused) + assert isinstance( + _verdict(PUBLICLY_KNOWN_KEY, {WEAK_OR_UNSET_MASTER_KEY_OVERRIDE_SETTING: False}), UnsafeMasterKeyRefused + ) def test_yaml_master_key_is_the_source_even_when_it_resolved_to_nothing(): @@ -98,8 +106,8 @@ def test_yaml_master_key_is_the_source_even_when_it_resolved_to_nothing(): def test_yaml_master_key_is_the_source_when_it_differs_from_the_environment(): verdict = _verdict( - "sk-1234", - {"master_key": "sk-1234"}, + PUBLICLY_KNOWN_KEY, + {"master_key": PUBLICLY_KNOWN_KEY}, environment_master_key="sk-qa-9f2c1e7a44b0d3", config_file_path="/app/config.yaml", ) @@ -108,7 +116,7 @@ def test_yaml_master_key_is_the_source_when_it_differs_from_the_environment(): assert verdict.source == ConfigFileSource(config_file_path="/app/config.yaml") -@pytest.mark.parametrize("unsafe_key", ["sk-1234", ""]) +@pytest.mark.parametrize("unsafe_key", [PUBLICLY_KNOWN_KEY, ""]) def test_environment_is_the_source_when_yaml_only_relays_the_environment_variable(unsafe_key: str): verdict = _verdict( unsafe_key, @@ -122,7 +130,9 @@ def test_environment_is_the_source_when_yaml_only_relays_the_environment_variabl def test_environment_is_the_source_when_yaml_does_not_set_a_master_key(): - verdict = _verdict("sk-1234", {"database_url": "postgresql://db"}, config_file_path="/app/config.yaml") + verdict = _verdict( + PUBLICLY_KNOWN_KEY, {"database_url": "postgresql://db"}, config_file_path="/app/config.yaml" + ) assert isinstance(verdict, UnsafeMasterKeyRefused) assert verdict.source == EnvironmentSource() @@ -131,11 +141,21 @@ def test_environment_is_the_source_when_yaml_does_not_set_a_master_key(): @pytest.mark.parametrize( ("master_key", "salt_key_is_set", "database_is_configured", "migration"), [ - ("sk-1234", False, True, StoredSecretsMigration(from_master_key="sk-1234", encrypted_value_count=None)), + ( + PUBLICLY_KNOWN_KEY, + False, + True, + StoredSecretsMigration(from_master_key=PUBLICLY_KNOWN_KEY, encrypted_value_count=None), + ), ("", False, True, StoredSecretsMigration(from_master_key="", encrypted_value_count=None)), - (" sk-1234\n", False, True, StoredSecretsMigration(from_master_key=" sk-1234\n", encrypted_value_count=None)), - ("sk-1234", True, True, None), - ("sk-1234", False, False, None), + ( + " " + PUBLICLY_KNOWN_KEY + "\n", + False, + True, + StoredSecretsMigration(from_master_key=" " + PUBLICLY_KNOWN_KEY + "\n", encrypted_value_count=None), + ), + (PUBLICLY_KNOWN_KEY, True, True, None), + (PUBLICLY_KNOWN_KEY, False, False, None), (None, False, True, None), ], ) @@ -162,11 +182,11 @@ def _counted(verdict: MasterKeyBootVerdict, count: int | None) -> tuple[MasterKe def test_database_with_nothing_encrypted_needs_no_migration(): - counted, asked_about = _counted(_verdict("sk-1234", database_is_configured=True), 0) + counted, asked_about = _counted(_verdict(PUBLICLY_KNOWN_KEY, database_is_configured=True), 0) assert isinstance(counted, UnsafeMasterKeyRefused) assert counted.migration is None - assert asked_about == ["sk-1234"] + assert asked_about == [PUBLICLY_KNOWN_KEY] @pytest.mark.parametrize("count", [4, None]) @@ -182,7 +202,7 @@ def test_database_with_encrypted_values_or_unreadable_keeps_the_migration(count: [ SafeMasterKey(), UnsafeMasterKeyAllowed(reason=UnsafeMasterKeyReason.PUBLICLY_KNOWN), - _verdict("sk-1234", database_is_configured=False), + _verdict(PUBLICLY_KNOWN_KEY, database_is_configured=False), ], ) def test_database_is_not_read_when_no_migration_is_on_the_table(verdict: MasterKeyBootVerdict): @@ -206,7 +226,7 @@ def _refusal( ) -_MIGRATION = StoredSecretsMigration(from_master_key="sk-1234", encrypted_value_count=3) +_MIGRATION = StoredSecretsMigration(from_master_key=PUBLICLY_KNOWN_KEY, encrypted_value_count=3) def test_config_refusal_names_the_file_and_tells_it_to_read_the_environment(): @@ -229,9 +249,9 @@ def test_environment_refusal_gives_the_command_without_a_config_step(): ("master_key", "general_settings", "environment_master_key", "is_set"), [ (None, {}, None, False), - ("sk-1234", {"master_key": "sk-1234"}, None, False), - ("sk-1234", {}, "sk-1234", True), - ("sk-1234", {"master_key": "sk-1234"}, "", True), + (PUBLICLY_KNOWN_KEY, {"master_key": PUBLICLY_KNOWN_KEY}, None, False), + (PUBLICLY_KNOWN_KEY, {}, PUBLICLY_KNOWN_KEY, True), + (PUBLICLY_KNOWN_KEY, {"master_key": PUBLICLY_KNOWN_KEY}, "", True), ], ) def test_refusal_records_whether_the_environment_variable_is_already_set( @@ -290,7 +310,7 @@ def test_migration_steps_appear_only_when_the_database_needs_them(): with_migration = render_refusal(_refusal(migration=_MIGRATION)) without_migration = render_refusal(_refusal(migration=None)) - assert f"{MIGRATE_FROM_MASTER_KEY_ENV_VAR}=sk-1234" in with_migration + assert f"{MIGRATE_FROM_MASTER_KEY_ENV_VAR}={PUBLICLY_KNOWN_KEY}" in with_migration assert "holds 3 value(s) encrypted with this master key" in with_migration assert ROTATION_DOCS_URL in with_migration assert MIGRATE_FROM_MASTER_KEY_ENV_VAR not in without_migration @@ -299,20 +319,20 @@ def test_migration_steps_appear_only_when_the_database_needs_them(): def test_unreadable_database_is_reported_as_unchecked_rather_than_counted(): text = render_refusal( - _refusal(migration=StoredSecretsMigration(from_master_key="sk-1234", encrypted_value_count=None)) + _refusal(migration=StoredSecretsMigration(from_master_key=PUBLICLY_KNOWN_KEY, encrypted_value_count=None)) ) assert "could not be checked" in text assert "value(s)" not in text - assert f"{MIGRATE_FROM_MASTER_KEY_ENV_VAR}=sk-1234" in text + assert f"{MIGRATE_FROM_MASTER_KEY_ENV_VAR}={PUBLICLY_KNOWN_KEY}" in text @pytest.mark.parametrize( ("from_master_key", "assignment"), [ - ("sk-1234", f"{MIGRATE_FROM_MASTER_KEY_ENV_VAR}=sk-1234"), + (PUBLICLY_KNOWN_KEY, f"{MIGRATE_FROM_MASTER_KEY_ENV_VAR}={PUBLICLY_KNOWN_KEY}"), ("", f"{MIGRATE_FROM_MASTER_KEY_ENV_VAR}="), - (" sk-1234", f'{MIGRATE_FROM_MASTER_KEY_ENV_VAR}=" sk-1234"'), + (" " + PUBLICLY_KNOWN_KEY, f'{MIGRATE_FROM_MASTER_KEY_ENV_VAR}=" {PUBLICLY_KNOWN_KEY}"'), ], ) def test_migrate_from_assignment_carries_the_exact_previous_key(from_master_key: str, assignment: str): @@ -342,7 +362,7 @@ def test_migration_with_an_exported_key_replaces_it_in_place_and_numbers_every_s @pytest.mark.skipif(shutil.which("openssl") is None, reason="the printed command shells out to openssl") -@pytest.mark.parametrize("from_master_key", ["sk-1234", "", " sk-1234"]) +@pytest.mark.parametrize("from_master_key", [PUBLICLY_KNOWN_KEY, "", " " + PUBLICLY_KNOWN_KEY]) def test_printed_migration_commands_save_both_keys_to_the_env_file(tmp_path: Path, from_master_key: str): from dotenv import dotenv_values diff --git a/tests/unit/proxy/auth/test_user_api_key_auth.py b/tests/unit/proxy/auth/test_user_api_key_auth.py index 1cfef5b3a6c..e84ecea2acd 100644 --- a/tests/unit/proxy/auth/test_user_api_key_auth.py +++ b/tests/unit/proxy/auth/test_user_api_key_auth.py @@ -21,6 +21,7 @@ from litellm.proxy.auth.user_api_key_auth import ( from fastapi import WebSocket, HTTPException, status from litellm.proxy._types import LiteLLM_UserTable, LitellmUserRoles +from tests._master_key import MASTER_KEY class Request: @@ -105,7 +106,7 @@ async def test_check_blocked_team(): from litellm.proxy.proxy_server import hash_token, user_api_key_cache _team_id = "1234" - user_key = "sk-12345678" + user_key = "sk-98765678" valid_token = UserAPIKeyAuth( team_id=_team_id, @@ -121,7 +122,7 @@ async def test_check_blocked_team(): user_api_key_cache.set_cache(key="team_id:{}".format(_team_id), value=team_obj) setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "hello-world") request = Request(scope={"type": "http", "method": "POST", "path": "/chat/completions", "headers": []}) @@ -146,7 +147,7 @@ async def test_team_object_has_object_permission_id(): team_id = "team-vector" permission_id = "perm-vector-123" - user_key = "sk-12345678" + user_key = "sk-98765678" hashed_key = hash_token(user_key) valid_token = UserAPIKeyAuth( @@ -159,7 +160,7 @@ async def test_team_object_has_object_permission_id(): user_api_key_cache.set_cache(key=hashed_key, value=valid_token) setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "test-client") request = Request(scope={"type": "http", "method": "POST", "path": "/chat/completions", "headers": []}) @@ -235,7 +236,7 @@ async def test_aaauser_personal_budgets(key_ownership): from litellm.proxy.proxy_server import hash_token, user_api_key_cache _user_id = "1234" - user_key = "sk-12345678" + user_key = "sk-98765678" if key_ownership == "user_key": valid_token = UserAPIKeyAuth( @@ -260,7 +261,7 @@ async def test_aaauser_personal_budgets(key_ownership): user_api_key_cache.set_cache(key="{}".format(_user_id), value=user_obj) setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", _NoMembershipRowPrisma()) request = Request(scope={"type": "http", "method": "POST", "path": "/chat/completions", "headers": []}) @@ -289,9 +290,9 @@ async def test_user_api_key_auth_fails_with_prohibited_params(prohibited_param): from fastapi import Request # Setup - user_key = "sk-1234" + user_key = MASTER_KEY - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) # Create request with prohibited parameter in body request = Request(scope={"type": "http", "method": "POST", "path": "/chat/completions", "headers": []}) @@ -322,7 +323,7 @@ async def test_user_api_key_auth_fails_with_prohibited_params(prohibited_param): ) async def test_auth_with_allowed_routes(route, should_raise_error): # Setup - user_key = "sk-1234" + user_key = MASTER_KEY general_settings = {"allowed_routes": ["/embeddings"]} from fastapi import Request @@ -331,7 +332,7 @@ async def test_auth_with_allowed_routes(route, should_raise_error): initial_general_settings = getattr(proxy_server, "general_settings") - setattr(proxy_server, "master_key", "sk-1234") + setattr(proxy_server, "master_key", MASTER_KEY) setattr(proxy_server, "general_settings", general_settings) request = Request(scope={"type": "http", "method": "POST", "path": route, "headers": []}) @@ -483,10 +484,10 @@ async def test_auth_not_connected_to_db(): from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.proxy.proxy_server import hash_token, user_api_key_cache - user_key = "sk-12345678" + user_key = "sk-98765678" setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", None) setattr( litellm.proxy.proxy_server, @@ -601,7 +602,7 @@ async def test_auth_with_form_data_and_model(): ) # Setup - user_key = "sk-12345678" + user_key = "sk-98765678" # Create a virtual key with a specific model valid_token = UserAPIKeyAuth( @@ -613,7 +614,7 @@ async def test_auth_with_form_data_and_model(): user_api_key_cache.set_cache(key=hash_token(user_key), value=valid_token) setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "hello-world") # Create request with form data @@ -655,7 +656,7 @@ async def test_soft_budget_alert(): from litellm.proxy.proxy_server import hash_token, user_api_key_cache # Setup - user_key = "sk-12345" + user_key = "sk-98765" soft_budget = 10 current_spend = 15 # Spend exceeds soft budget @@ -672,7 +673,7 @@ async def test_soft_budget_alert(): # Mock proxy server settings setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", AsyncMock()) # Create request @@ -983,7 +984,7 @@ def test_user_api_key_auth_end_user_str(): from litellm.proxy.auth.user_api_key_auth import UserAPIKeyAuth user_api_key_args = { - "api_key": "sk-1234", + "api_key": MASTER_KEY, "parent_otel_span": None, "user_role": LitellmUserRoles.PROXY_ADMIN, "end_user_id": "1", @@ -1153,7 +1154,7 @@ async def test_x_litellm_api_key(): from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.proxy.proxy_server import hash_token, user_api_key_cache - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) setattr(litellm.proxy.proxy_server, "master_key", master_key) @@ -1188,7 +1189,7 @@ async def test_user_api_key_from_query_param(): user_api_key_cache.set_cache(key=hash_token(user_key), value=UserAPIKeyAuth(token=hash_token(user_key))) setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "hello-world") request = Request( @@ -1272,7 +1273,7 @@ async def test_user_model_max_budget_is_threaded_onto_the_auth_object(): auth_obj = await _return_user_api_key_auth_obj( user_obj=user_obj, - api_key="sk-1234", + api_key=MASTER_KEY, parent_otel_span=None, valid_token_dict={"token": "hash"}, route="/chat/completions", @@ -1317,7 +1318,7 @@ async def test_user_model_budget_is_enforced_through_user_api_key_auth(over_budg user_model_max_budget = {model: {"budget_limit": 1.0, "time_period": "1mo"}} setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "present") await user_api_key_cache.async_set_cache( diff --git a/tests/unit/proxy/auth/test_user_api_key_auth_request_flow.py b/tests/unit/proxy/auth/test_user_api_key_auth_request_flow.py index 8b33202b483..d4d11527994 100644 --- a/tests/unit/proxy/auth/test_user_api_key_auth_request_flow.py +++ b/tests/unit/proxy/auth/test_user_api_key_auth_request_flow.py @@ -65,6 +65,7 @@ from litellm.proxy.auth.user_api_key_auth import ( ) from litellm.proxy.spend_tracking.carried_budget_state import carried_budget_metadata from tests.unit.proxy.db.fake_prisma_engine import engine_call +from tests._master_key import MASTER_KEY class _RoutingRequest: @@ -75,9 +76,9 @@ class _RoutingRequest: def test_get_api_key(): - bearer_token = "Bearer sk-12345678" - api_key = "sk-12345678" - passed_in_key = "Bearer sk-12345678" + bearer_token = "Bearer sk-98765678" + api_key = "sk-98765678" + passed_in_key = "Bearer sk-98765678" assert get_api_key( custom_litellm_key_header=None, api_key=bearer_token, @@ -2821,7 +2822,7 @@ class TestJWTOAuth2Coexistence: def test_is_jwt_rejects_opaque_tokens(self): """Opaque OAuth2 tokens do not have 3 dot-separated parts.""" assert JWTHandler.is_jwt("some-opaque-oauth2-token") is False - assert JWTHandler.is_jwt("sk-12345678") is False + assert JWTHandler.is_jwt("sk-98765678") is False assert JWTHandler.is_jwt("Bearer token") is False assert JWTHandler.is_jwt("two.parts") is False @@ -9715,7 +9716,7 @@ async def test_websocket_auth_hands_the_reservation_to_the_socket_state(): scope={ "type": "websocket", "path": "/v1/realtime", - "headers": [(b"authorization", b"Bearer sk-1234")], + "headers": [(b"authorization", b"Bearer sk-9876")], "query_string": b"model=gpt-realtime", }, receive=AsyncMock(), @@ -9812,8 +9813,8 @@ def test_identity_prefetch_keys_match_what_auth_reads_for_the_request(): ) from litellm.proxy.utils import hash_token - assert _identity_cache_keys("sk-1234", end_user_id="eu-1", key_is_resolved=False) == ( - hash_token("sk-1234"), + assert _identity_cache_keys(MASTER_KEY, end_user_id="eu-1", key_is_resolved=False) == ( + hash_token(MASTER_KEY), end_user_cache_key("eu-1"), end_user_restricted_registry_cache_key(), model_access_group_registry_cache_key(), @@ -9825,7 +9826,7 @@ def test_identity_prefetch_keys_match_what_auth_reads_for_the_request(): master_key_keys = _identity_cache_keys("my-master-key", end_user_id=None, key_is_resolved=False) assert master_key_keys == (hash_token("my-master-key"), model_access_group_registry_cache_key()) assert "my-master-key" not in master_key_keys, "a bearer that is not an sk- key must not be sent to Redis as is" - assert _identity_cache_keys("sk-1234", end_user_id=None, key_is_resolved=True) == ( + assert _identity_cache_keys(MASTER_KEY, end_user_id=None, key_is_resolved=True) == ( model_access_group_registry_cache_key(), ) diff --git a/tests/unit/proxy/client/test_keys.py b/tests/unit/proxy/client/test_keys.py index b9b07bddf1f..3bff944144c 100644 --- a/tests/unit/proxy/client/test_keys.py +++ b/tests/unit/proxy/client/test_keys.py @@ -419,7 +419,7 @@ def test_info_server_error(client): client.info(key="test-key") -LEAKY_KEY = "sk-1234567890abcdefghijklmnop" +LEAKY_KEY = "sk-9876567890abcdefghijklmnop" def _render_full_traceback(exc: BaseException) -> str: diff --git a/tests/unit/proxy/common_utils/test_encrypt_decrypt_utils.py b/tests/unit/proxy/common_utils/test_encrypt_decrypt_utils.py index 5b7d35c3b46..7c07f19d72f 100644 --- a/tests/unit/proxy/common_utils/test_encrypt_decrypt_utils.py +++ b/tests/unit/proxy/common_utils/test_encrypt_decrypt_utils.py @@ -198,9 +198,9 @@ def test_decrypt_failure_debug_log_omits_raw_value(monkeypatch): def test_explicit_key_decrypt_reads_only_values_written_under_that_key(monkeypatch, use_aes: bool): if use_aes: _use_aes(monkeypatch) - written_with_previous_key = encrypt_value_helper("stored-secret", new_encryption_key="sk-1234") + written_with_previous_key = encrypt_value_helper("stored-secret", new_encryption_key="sk-9876") - assert decrypt_if_encrypted_with(written_with_previous_key, "sk-1234") == "stored-secret" + assert decrypt_if_encrypted_with(written_with_previous_key, "sk-9876") == "stored-secret" assert decrypt_if_encrypted_with(written_with_previous_key, "sk-another-key") is None assert decrypt_value_helper(written_with_previous_key, key="t", exception_type="debug") is None @@ -224,7 +224,7 @@ def test_explicit_key_decrypt_reads_only_values_written_under_that_key(monkeypat ], ) def test_explicit_key_decrypt_rejects_values_that_are_not_ciphertexts(not_a_ciphertext: str): - assert decrypt_if_encrypted_with(not_a_ciphertext, "sk-1234") is None + assert decrypt_if_encrypted_with(not_a_ciphertext, "sk-9876") is None @pytest.mark.parametrize("use_aes", [False, True]) @@ -232,7 +232,7 @@ def test_explicit_key_decrypt_tells_an_encrypted_empty_string_from_no_ciphertext if use_aes: _use_aes(monkeypatch) - assert decrypt_if_encrypted_with(encrypt_value_helper("", new_encryption_key="sk-1234"), "sk-1234") == "" + assert decrypt_if_encrypted_with(encrypt_value_helper("", new_encryption_key="sk-9876"), "sk-9876") == "" def test_explicit_key_decrypt_supports_the_empty_master_key(): diff --git a/tests/unit/proxy/common_utils/test_http_parsing_utils.py b/tests/unit/proxy/common_utils/test_http_parsing_utils.py index 16821222782..f8597f71c5b 100644 --- a/tests/unit/proxy/common_utils/test_http_parsing_utils.py +++ b/tests/unit/proxy/common_utils/test_http_parsing_utils.py @@ -495,7 +495,7 @@ async def test_json_parsing_error_handling(): "type": "mcp", "server_label": "litellm", "headers": { - "x-litellm-api-key": "Bearer sk-1234", + "x-litellm-api-key": "Bearer sk-9876", } } ], @@ -547,7 +547,7 @@ async def test_json_parsing_error_handling(): "type": "mcp", "server_label": "litellm", "headers": { - "x-litellm-api-key": "Bearer sk-1234" + "x-litellm-api-key": "Bearer sk-9876" } } ], diff --git a/tests/unit/proxy/common_utils/test_key_rotation_integration.py b/tests/unit/proxy/common_utils/test_key_rotation_integration.py index 6103a40d6c7..8ab182735c4 100644 --- a/tests/unit/proxy/common_utils/test_key_rotation_integration.py +++ b/tests/unit/proxy/common_utils/test_key_rotation_integration.py @@ -197,7 +197,7 @@ class TestKeyRotationSecretNamingStability: existing_key_row=existing_key, response=response, user_api_key_dict=UserAPIKeyAuth( - user_role="proxy_admin", api_key="sk-1234", user_id="1234" + user_role="proxy_admin", api_key="sk-9876", user_id="1234" ), ) diff --git a/tests/unit/proxy/common_utils/test_load_config_utils.py b/tests/unit/proxy/common_utils/test_load_config_utils.py index 1042dbe9653..927e6ee511d 100644 --- a/tests/unit/proxy/common_utils/test_load_config_utils.py +++ b/tests/unit/proxy/common_utils/test_load_config_utils.py @@ -13,6 +13,7 @@ from litellm.proxy.common_utils.load_config_utils import ( get_file_contents_from_s3, resolve_bucket_includes, ) +from tests._master_key import MASTER_KEY class TestGetFileContentsFromS3: @@ -106,7 +107,7 @@ class TestBucketConfigIncludes: @pytest.mark.asyncio async def test_include_resolves_against_the_config_objects_prefix(self): merged = await resolve_bucket_includes( - config={"include": ["model_config.yaml"], "general_settings": {"master_key": "sk-1234"}}, + config={"include": ["model_config.yaml"], "general_settings": {"master_key": MASTER_KEY}}, object_key="configs/prod/config.yaml", fetch=self._bucket( {"configs/prod/model_config.yaml": {"model_list": [{"model_name": "gpt-4o-mini"}]}} @@ -114,7 +115,7 @@ class TestBucketConfigIncludes: ) assert merged == { - "general_settings": {"master_key": "sk-1234"}, + "general_settings": {"master_key": MASTER_KEY}, "model_list": [{"model_name": "gpt-4o-mini"}], } @@ -256,7 +257,7 @@ class TestBucketConfigIncludes: objects = { "lit6982/config.yaml": { "include": ["model_config.yaml"], - "general_settings": {"master_key": "sk-1234"}, + "general_settings": {"master_key": MASTER_KEY}, }, "lit6982/model_config.yaml": {"model_list": [{"model_name": "included-model"}]}, } @@ -270,7 +271,7 @@ class TestBucketConfigIncludes: ) assert config == { - "general_settings": {"master_key": "sk-1234"}, + "general_settings": {"master_key": MASTER_KEY}, "model_list": [{"model_name": "included-model"}], } @@ -347,7 +348,7 @@ class TestBucketConfigIncludes: objects = { "lit6982/config.yaml": { "include": ["model_config.yaml"], - "general_settings": {"master_key": "sk-1234"}, + "general_settings": {"master_key": MASTER_KEY}, }, "lit6982/model_config.yaml": {"model_list": [{"model_name": "included-model"}]}, } @@ -373,7 +374,7 @@ class TestBucketConfigIncludes: ) assert config == { - "general_settings": {"master_key": "sk-1234"}, + "general_settings": {"master_key": MASTER_KEY}, "model_list": [{"model_name": "included-model"}], } assert [bucket.requested for bucket in buckets] == [ diff --git a/tests/unit/proxy/common_utils/test_proxy_encrypt_decrypt.py b/tests/unit/proxy/common_utils/test_proxy_encrypt_decrypt.py index 88ee64b6c4b..d40f180f421 100644 --- a/tests/unit/proxy/common_utils/test_proxy_encrypt_decrypt.py +++ b/tests/unit/proxy/common_utils/test_proxy_encrypt_decrypt.py @@ -12,10 +12,11 @@ from litellm.proxy.common_utils.encrypt_decrypt_utils import ( decrypt_value_helper, encrypt_value_helper, ) +from tests._master_key import MASTER_KEY def test_encrypt_decrypt_with_master_key(): - setattr(proxy_server, "master_key", "sk-1234") + setattr(proxy_server, "master_key", MASTER_KEY) assert decrypt_value_helper(encrypt_value_helper("test"), key="test_key") == "test" assert decrypt_value_helper(encrypt_value_helper(10), key="test_key") == 10 assert decrypt_value_helper(encrypt_value_helper(True), key="test_key") is True diff --git a/tests/unit/proxy/conftest.py b/tests/unit/proxy/conftest.py index cb7e9969bca..d86bdd84a62 100644 --- a/tests/unit/proxy/conftest.py +++ b/tests/unit/proxy/conftest.py @@ -21,6 +21,7 @@ from litellm._service_logger import ServiceTypes from litellm.integrations.otel.model.payloads import ServiceSpanData from litellm.integrations.otel.model.spans import service_span_name from tests.unit.litellm_core_utils.fake_secret_vault import FakeSecretVault +from tests._master_key import MASTER_KEY class StubClientNotConnectedError(ClientNotConnectedError): @@ -294,7 +295,7 @@ def build_minimal_proxy_config( Args: database_url: Optional database URL (falls back to DATABASE_URL env var) **init_options: Additional configuration options: - - master_key: API key for authentication (default: "sk-1234") + - master_key: API key for authentication (default: MASTER_KEY) - enable_cache: Whether to enable Redis cache (default: True) - success_callback: Callback function for success events @@ -302,7 +303,7 @@ def build_minimal_proxy_config( dict: Configuration dictionary ready to be written as YAML """ config = { - "general_settings": {"master_key": init_options.get("master_key", "sk-1234")}, + "general_settings": {"master_key": init_options.get("master_key", MASTER_KEY)}, "litellm_settings": {}, } @@ -367,7 +368,7 @@ def create_proxy_test_client( monkeypatch: pytest monkeypatch fixture database_url: Optional database URL (falls back to DATABASE_URL env var) **init_options: Additional configuration options: - - master_key: API key for authentication (default: "sk-1234") + - master_key: API key for authentication (default: MASTER_KEY) - enable_cache: Whether to enable Redis cache (default: True) - success_callback: Callback function for success events - debug: Enable debug mode diff --git a/tests/unit/proxy/db/db_transaction_queue/test_e2e_pod_lock_manager.py b/tests/unit/proxy/db/db_transaction_queue/test_e2e_pod_lock_manager.py index e90184ce45b..d2c6b661068 100644 --- a/tests/unit/proxy/db/db_transaction_queue/test_e2e_pod_lock_manager.py +++ b/tests/unit/proxy/db/db_transaction_queue/test_e2e_pod_lock_manager.py @@ -85,6 +85,7 @@ from litellm.proxy._types import ( UpdateUserRequest, UserAPIKeyAuth, ) +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -123,7 +124,7 @@ def prisma_client(): async def setup_db_connection(prisma_client): setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() diff --git a/tests/unit/proxy/db/test_master_key_migration.py b/tests/unit/proxy/db/test_master_key_migration.py index 47e218789af..ebd76084e8d 100644 --- a/tests/unit/proxy/db/test_master_key_migration.py +++ b/tests/unit/proxy/db/test_master_key_migration.py @@ -22,8 +22,9 @@ from litellm.proxy.db.master_key_migration import ( reencrypt_stored_values, replace_ciphertexts, ) +from tests._master_key import MASTER_KEY -PREVIOUS_KEY = "sk-1234" +PREVIOUS_KEY = MASTER_KEY NEW_KEY = "sk-qa-9f2c1e7a44b0d3" UNRELATED_KEY = "sk-some-other-deployment" diff --git a/tests/unit/proxy/guardrails/guardrail_hooks/test_panw_prisma_airs.py b/tests/unit/proxy/guardrails/guardrail_hooks/test_panw_prisma_airs.py index dba67e7b7bc..a5c543528c2 100644 --- a/tests/unit/proxy/guardrails/guardrail_hooks/test_panw_prisma_airs.py +++ b/tests/unit/proxy/guardrails/guardrail_hooks/test_panw_prisma_airs.py @@ -3938,7 +3938,7 @@ class TestPanwAirsDeveloperRoleGuardrail: data = { "messages": [ - {"role": "developer", "content": "secret API key: sk-12345"}, + {"role": "developer", "content": "secret API key: sk-98765"}, ], "model": "gpt-4", "litellm_call_id": "test-call-id", @@ -3959,7 +3959,7 @@ class TestPanwAirsDeveloperRoleGuardrail: mock_api.assert_called_once() # Verify the developer content was sent to the API call_args = mock_api.call_args - assert "secret API key: sk-12345" in str(call_args) + assert "secret API key: sk-98765" in str(call_args) class TestPanwAirsEmptyToolArgsBlock: diff --git a/tests/unit/proxy/guardrails/guardrail_hooks/test_straiker.py b/tests/unit/proxy/guardrails/guardrail_hooks/test_straiker.py index 862152e3839..292dd54105f 100644 --- a/tests/unit/proxy/guardrails/guardrail_hooks/test_straiker.py +++ b/tests/unit/proxy/guardrails/guardrail_hooks/test_straiker.py @@ -1118,11 +1118,11 @@ def _v3_request_data(**overrides) -> dict: "user_api_key_user_id": "default_user_id", "user_api_key_alias": "litellm_proxy_master_key", "session_id": "v3qa-1", - "headers": {"authorization": "Bearer sk-1234"}, + "headers": {"authorization": "Bearer sk-9876"}, }, "proxy_server_request": { "url": "http://localhost:4141/v1/chat/completions", - "headers": {"authorization": "Bearer sk-1234", "x-claude-code-session-id": "cc-sess-9"}, + "headers": {"authorization": "Bearer sk-9876", "x-claude-code-session-id": "cc-sess-9"}, }, "litellm_call_id": "call-123", "deployment": {"litellm_params": {"api_key": "sk-ant-PROVIDER-SECRET"}}, @@ -1298,7 +1298,7 @@ async def test_v3_request_phase_relays_the_provider_body_and_nothing_else(): "litellm_call_id", "provider_specific_header", "PROVIDER-SECRET", - "Bearer sk-1234", + "Bearer sk-9876", "default_user_id", "litellm_proxy_master_key", ): @@ -1485,7 +1485,7 @@ async def test_v3_agent_hint_enumerates_per_app_and_the_route_config_wins(): pinned = _make_guardrail(api_key=V3_KEY, agent_ref="billing-bot") pinned.async_handler.post.return_value = _v3_mock(V3_GATEWAY_ALLOW) data = _v3_request_data() - data["proxy_server_request"] = {"headers": {"authorization": "Bearer sk-1234"}} + data["proxy_server_request"] = {"headers": {"authorization": "Bearer sk-9876"}} await pinned.apply_guardrail( inputs={"texts": ["hi"]}, request_data=data, input_type="request", logging_obj=_logging_obj() ) @@ -1699,7 +1699,7 @@ CLAUDE_CODE_HEADERS = { "user-agent": "claude-cli/2.0.21 (external, claude-vscode, agent-sdk/0.3.27)", "x-app": "cli", "anthropic-beta": "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14", - "authorization": "Bearer sk-1234", + "authorization": "Bearer sk-9876", } @@ -1766,7 +1766,7 @@ async def test_v3_client_config_wins_over_the_user_agent_and_unknown_agents_send curl = _v3_request_data( proxy_server_request={ "url": "http://localhost:4141/v1/chat/completions", - "headers": {"user-agent": "curl/8.7.1", "authorization": "Bearer sk-1234"}, + "headers": {"user-agent": "curl/8.7.1", "authorization": "Bearer sk-9876"}, } ) await g2.apply_guardrail( @@ -1843,7 +1843,7 @@ async def test_v3_legacy_completion_is_presented_as_one_chat_exchange(): completion.pop(key) completion["proxy_server_request"] = { "url": "http://localhost:4141/v1/completions", - "headers": {"authorization": "Bearer sk-1234"}, + "headers": {"authorization": "Bearer sk-9876"}, } await g.apply_guardrail( @@ -2107,7 +2107,7 @@ def _completion_call(prompt): data.pop(key) data["proxy_server_request"] = { "url": "http://localhost:4141/v1/completions", - "headers": {"authorization": "Bearer sk-1234"}, + "headers": {"authorization": "Bearer sk-9876"}, } return data diff --git a/tests/unit/proxy/guardrails/test_guardrail_endpoints.py b/tests/unit/proxy/guardrails/test_guardrail_endpoints.py index a3d4786f7d1..2b117f05b92 100644 --- a/tests/unit/proxy/guardrails/test_guardrail_endpoints.py +++ b/tests/unit/proxy/guardrails/test_guardrail_endpoints.py @@ -223,7 +223,7 @@ async def test_list_guardrails_v2_masks_sensitive_data_in_db_guardrails(mocker): "litellm_params": { "guardrail": "azure/text_moderations", "mode": "pre_call", - "api_key": "sk-1234567890abcdef", + "api_key": "sk-9876567890abcdef", "api_base": "https://api.secret.example.com", }, "guardrail_info": {"description": "Test guardrail"}, @@ -257,7 +257,7 @@ async def test_list_guardrails_v2_masks_sensitive_data_in_db_guardrails(mocker): params = litellm_params.model_dump() if hasattr(litellm_params, "model_dump") else dict(litellm_params) # Sensitive keys (containing "key", "secret", "token", etc.) should be masked - assert params["api_key"] != "sk-1234567890abcdef" + assert params["api_key"] != "sk-9876567890abcdef" assert "****" in str(params["api_key"]) # Non-sensitive keys should remain unchanged assert params["guardrail"] == "azure/text_moderations" diff --git a/tests/unit/proxy/hooks/test_banned_keyword_list.py b/tests/unit/proxy/hooks/test_banned_keyword_list.py index 35e625a6b9e..82ab693e699 100644 --- a/tests/unit/proxy/hooks/test_banned_keyword_list.py +++ b/tests/unit/proxy/hooks/test_banned_keyword_list.py @@ -31,8 +31,8 @@ async def test_banned_keywords_check(): banned_keywords_obj = _ENTERPRISE_BannedKeywords() - _api_key = "sk-12345" - _api_key = hash_token("sk-12345") + _api_key = "sk-98765" + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key) local_cache = DualCache() diff --git a/tests/unit/proxy/hooks/test_parallel_request_limiter.py b/tests/unit/proxy/hooks/test_parallel_request_limiter.py index a83ddc69863..c42d3b51799 100644 --- a/tests/unit/proxy/hooks/test_parallel_request_limiter.py +++ b/tests/unit/proxy/hooks/test_parallel_request_limiter.py @@ -57,7 +57,7 @@ async def test_async_log_success_event_counts_non_chat_response_tokens(response_ team, and end user TPM counters, not just chat completion ModelResponse objects. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") user_id = "ishaan" team_id = "litellm-team" end_user_id = "customer-1" diff --git a/tests/unit/proxy/hooks/test_parallel_request_limiter_v3.py b/tests/unit/proxy/hooks/test_parallel_request_limiter_v3.py index d3a723fe1d3..783e544eb6c 100644 --- a/tests/unit/proxy/hooks/test_parallel_request_limiter_v3.py +++ b/tests/unit/proxy/hooks/test_parallel_request_limiter_v3.py @@ -271,7 +271,7 @@ async def test_sliding_window_rate_limit_v3(monkeypatch, time_controller): Test the sliding window rate limiting functionality """ monkeypatch.setenv("LITELLM_RATE_LIMIT_WINDOW_SIZE", "2") - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, rpm_limit=3) local_cache = DualCache() @@ -364,7 +364,7 @@ async def test_rate_limiter_script_return_values_v3(monkeypatch, time_controller Test that the rate limiter script returns both counter and window values correctly """ monkeypatch.setenv("LITELLM_RATE_LIMIT_WINDOW_SIZE", "2") - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, rpm_limit=3) local_cache = DualCache() @@ -505,7 +505,7 @@ async def test_normal_router_call_tpm_v3( num_retries=3, ) # type: ignore - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) if rate_limit_object == "api_key": user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, tpm_limit=10) @@ -682,7 +682,7 @@ async def test_token_rate_limit_type_respected_v3(monkeypatch, token_rate_limit_ # Set up environment and mock general_settings monkeypatch.setenv("LITELLM_RATE_LIMIT_WINDOW_SIZE", "60") - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, tpm_limit=100) local_cache = DualCache() @@ -792,7 +792,7 @@ async def test_async_log_success_event_counts_non_chat_response_tokens( """ monkeypatch.setenv("LITELLM_RATE_LIMIT_WINDOW_SIZE", "60") - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") parallel_request_handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(DualCache()) ) @@ -839,7 +839,7 @@ async def test_async_log_failure_event_v3(): no-ops that can never free another request's slot (releasing more than was acquired is what previously let concurrency exceed the limit). """ - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) local_cache = DualCache() parallel_request_handler = _PROXY_MaxParallelRequestsHandler( @@ -892,7 +892,7 @@ async def test_failure_event_without_acquired_slot_does_not_release_v3(): above the configured limit. Without the acquired-slot marker the gauge must stay untouched. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -934,7 +934,7 @@ async def test_max_parallel_requests_not_reset_by_window_roll_v3(): internal_usage_cache=InternalUsageCache(local_cache), time_provider=controller.now, ) - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=2) for _ in range(2): @@ -970,7 +970,7 @@ async def test_rejected_request_does_not_consume_parallel_slot_v3(): handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) ) - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1) admitted_data: Dict[str, Any] = {"model": "gpt-3.5-turbo"} @@ -1025,7 +1025,7 @@ async def test_parallel_gauge_uses_atomic_redis_script_v3(): handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) ) - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=5) counter_key = f"{{api_key:{_api_key}}}:max_parallel_requests" @@ -1095,7 +1095,7 @@ async def test_should_rate_limit_only_called_when_limits_exist_v3(): Test that should_rate_limit is only called when actual rate limits are configured. This verifies the optimization that avoids unnecessary rate limit checks. """ - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) local_cache = DualCache() parallel_request_handler = _PROXY_MaxParallelRequestsHandler( @@ -1237,7 +1237,7 @@ async def test_model_specific_rate_limits_only_called_when_configured_v3(): get_key_model_tpm_limit, ) - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) local_cache = DualCache() parallel_request_handler = _PROXY_MaxParallelRequestsHandler( @@ -1298,7 +1298,7 @@ async def test_model_specific_rate_limits_only_called_when_configured_v3(): @pytest.mark.asyncio async def test_tpm_api_key_rate_limits_v3(): - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key_hash = hash_token(_api_key) model = "gpt-3.5-turbo" rpm_limit = 2 @@ -1393,7 +1393,7 @@ async def test_tpm_api_key_rate_limits_v3(): @pytest.mark.asyncio async def test_rpm_api_key_rate_limits_v3(): - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key_hash = hash_token(_api_key) model = "gpt-3.5-turbo" rpm_limit = 2 @@ -1490,7 +1490,7 @@ async def test_team_member_rate_limits_v3(): """ Test that team member RPM/TPM rate limits are properly applied for team member combinations. """ - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _team_id = "team_123" _user_id = "user_456" @@ -1559,7 +1559,7 @@ async def test_team_member_rate_limits_v3_raises_429_when_over_limit(): pre-call hook raises HTTP 429 with rate_limit headers — same contract as test_rpm_api_key_rate_limits_v3 / test_tpm_api_key_rate_limits_v3. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") _team_id = "team_123" _user_id = "user_456" @@ -1638,7 +1638,7 @@ async def test_dynamic_rate_limiting_v3(): - If model has no failures, rate limits should NOT be enforced (allow exceeding) - If model has failures above threshold, rate limits SHOULD be enforced """ - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key_hash = hash_token(_api_key) model = "gpt-3.5-turbo" @@ -1949,7 +1949,7 @@ async def test_multiple_rate_limits_per_descriptor(): 3. The old floor(i / 2) mapping would fail with IndexError 4. The new descriptor_key-based lookup works correctly """ - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key_hash = hash_token(_api_key) # Create a user with multiple rate limit types to trigger multiple statuses per descriptor @@ -2032,7 +2032,7 @@ async def test_missing_descriptor_fallback(): This tests an edge case where somehow the descriptor_key in status doesn't match any descriptor key (shouldn't happen in normal operation but good for robustness). """ - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key_hash = hash_token(_api_key) user_api_key_dict = UserAPIKeyAuth( @@ -2153,7 +2153,7 @@ async def test_async_log_success_event_with_dict_usage( """ from unittest.mock import MagicMock - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) local_cache = DualCache() parallel_request_handler = _PROXY_MaxParallelRequestsHandler( @@ -2243,7 +2243,7 @@ async def test_async_log_success_event_with_dict_usage_missing_fields(monkeypatc """ from unittest.mock import MagicMock - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) local_cache = DualCache() parallel_request_handler = _PROXY_MaxParallelRequestsHandler( @@ -2389,7 +2389,7 @@ async def test_agent_level_rate_limit_descriptors(): from litellm.types.agents import AgentResponse - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _agent_id = "agent_abc123" @@ -2455,7 +2455,7 @@ async def test_agent_session_rate_limit_descriptors(): from litellm.types.agents import AgentResponse - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _agent_id = "agent_abc123" _session_id = "sess_xyz789" @@ -2525,7 +2525,7 @@ async def test_agent_session_rate_limit_skipped_without_session_id(): from litellm.types.agents import AgentResponse - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _agent_id = "agent_abc123" @@ -2585,7 +2585,7 @@ async def test_agent_rate_limit_from_metadata_agent_id(): from litellm.types.agents import AgentResponse - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _agent_id = "agent_from_header" @@ -2654,7 +2654,7 @@ async def test_agent_both_agent_and_session_rate_limits(): from litellm.types.agents import AgentResponse - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _agent_id = "agent_dual" _session_id = "sess_dual" @@ -2728,7 +2728,7 @@ async def test_agent_rate_limit_tpm_increment_on_success(monkeypatch): Test that async_log_success_event increments agent and session TPM counters when agent_id and session_id are in metadata. """ - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _agent_id = "agent_tpm_test" _session_id = "sess_tpm_test" @@ -2814,7 +2814,7 @@ async def test_agent_rate_limit_429_on_over_limit(monkeypatch, time_controller): from litellm.types.agents import AgentResponse monkeypatch.setenv("LITELLM_RATE_LIMIT_WINDOW_SIZE", "2") - _api_key = "sk-12345" + _api_key = "sk-98765" _api_key = hash_token(_api_key) _agent_id = "agent_429_test" @@ -4181,7 +4181,7 @@ async def test_release_max_parallel_requests_on_disconnect_v3(): by one per cancelled request until the key wedges at its limit. The release must decrement the api-key max_parallel_requests counter by exactly one. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4214,7 +4214,7 @@ async def test_release_on_disconnect_works_when_key_config_changed_v3(): cleared on the key while a request is in flight, the acquired slot still has to be released or it lingers until TTL pruning. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4245,7 +4245,7 @@ async def test_post_call_failure_hook_releases_parallel_slot_v3(): rejection rates wedge the key at its limit. The release must also be idempotent with a later failure callback in the same flow. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4300,7 +4300,7 @@ async def test_success_event_releases_parallel_slot_v3(monkeypatch): acquired, freeing capacity for the next request; without it every completed request would keep occupying the gauge until TTL pruning. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4350,7 +4350,7 @@ async def test_read_only_gauge_check_counts_without_acquiring_v3(): a count-script failure must degrade to the local mirror instead of raising. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4407,7 +4407,7 @@ async def test_redis_release_script_updates_local_mirror_v3(): request's slot id per gauge key, and the returned in-flight counts are mirrored into the local cache so the local first-pass check stays fresh. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4447,7 +4447,7 @@ async def test_tpm_over_limit_rejection_releases_parallel_slot_v3(monkeypatch): slot until TTL pruning. """ monkeypatch.delenv("LITELLM_TPM_TOKEN_RESERVATION_ENABLED", raising=False) - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4496,7 +4496,7 @@ async def test_in_memory_fallback_respects_mirrored_redis_count_v3(): registry, which would double the admitted concurrency during a Redis outage. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) @@ -4548,7 +4548,7 @@ async def test_release_max_parallel_requests_on_disconnect_noop_v3(): (no api_key, or max_parallel_requests unset). Otherwise a cancelled no-limit request would drive an unrelated counter negative. """ - _api_key = hash_token("sk-12345") + _api_key = hash_token("sk-98765") local_cache = DualCache() handler = _PROXY_MaxParallelRequestsHandler( internal_usage_cache=InternalUsageCache(local_cache) diff --git a/tests/unit/proxy/management_endpoints/management_v1/test_teams.py b/tests/unit/proxy/management_endpoints/management_v1/test_teams.py index 33192ac574e..3f60384cfa7 100644 --- a/tests/unit/proxy/management_endpoints/management_v1/test_teams.py +++ b/tests/unit/proxy/management_endpoints/management_v1/test_teams.py @@ -769,7 +769,7 @@ def prisma(monkeypatch): def _post(body: object, path: str = BULK_UPDATE_PATH): - return client.post(path, json=body, headers={"Authorization": "Bearer sk-1234"}) + return client.post(path, json=body, headers={"Authorization": "Bearer sk-9876"}) def test_unknown_fields_empty_and_oversized_batches_are_422_problem_documents(prisma, as_proxy_admin): diff --git a/tests/unit/proxy/management_endpoints/search_endpoints/test_search_tool_management.py b/tests/unit/proxy/management_endpoints/search_endpoints/test_search_tool_management.py index cebaa037b48..582f6e82f11 100644 --- a/tests/unit/proxy/management_endpoints/search_endpoints/test_search_tool_management.py +++ b/tests/unit/proxy/management_endpoints/search_endpoints/test_search_tool_management.py @@ -466,7 +466,7 @@ async def test_list_search_tools_db_masking_sensitive_values(monkeypatch): "search_tool_name": "perplexity-tool", "litellm_params": { "search_provider": "perplexity", - "api_key": "pplx-sk-1234567890abcdef", + "api_key": "pplx-sk-9876567890abcdef", "api_base": "https://api.perplexity.ai", }, "search_tool_info": {"description": "Perplexity tool"}, @@ -552,7 +552,7 @@ async def test_list_search_tools_db_masking_sensitive_values(monkeypatch): ) assert tool1 is not None assert ( - tool1["litellm_params"]["api_key"] != "pplx-sk-1234567890abcdef" + tool1["litellm_params"]["api_key"] != "pplx-sk-9876567890abcdef" ) assert "****" in tool1["litellm_params"]["api_key"] assert tool1["litellm_params"]["search_provider"] == "perplexity" diff --git a/tests/unit/proxy/management_endpoints/test_callback_management_endpoints.py b/tests/unit/proxy/management_endpoints/test_callback_management_endpoints.py index 8f19cf6329c..b64877f7816 100644 --- a/tests/unit/proxy/management_endpoints/test_callback_management_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_callback_management_endpoints.py @@ -52,7 +52,7 @@ class TestCallbackManagementEndpoints: # Make request to list callbacks endpoint response = client.get( - "/callbacks/list", headers={"Authorization": "Bearer sk-1234"} + "/callbacks/list", headers={"Authorization": "Bearer sk-9876"} ) # Verify response @@ -87,7 +87,7 @@ class TestCallbackManagementEndpoints: # Make request to list callbacks endpoint response = client.get( - "/callbacks/list", headers={"Authorization": "Bearer sk-1234"} + "/callbacks/list", headers={"Authorization": "Bearer sk-9876"} ) # Verify response @@ -118,7 +118,7 @@ class TestCallbackManagementEndpoints: # Make request to list callbacks endpoint response = client.get( - "/callbacks/list", headers={"Authorization": "Bearer sk-1234"} + "/callbacks/list", headers={"Authorization": "Bearer sk-9876"} ) # Verify response @@ -155,7 +155,7 @@ class TestCallbackManagementEndpoints: # Make request to list callbacks endpoint response = client.get( - "/callbacks/list", headers={"Authorization": "Bearer sk-1234"} + "/callbacks/list", headers={"Authorization": "Bearer sk-9876"} ) # Verify response @@ -195,7 +195,7 @@ class TestCallbackManagementEndpoints: # Make request to list callbacks endpoint response = client.get( - "/callbacks/list", headers={"Authorization": "Bearer sk-1234"} + "/callbacks/list", headers={"Authorization": "Bearer sk-9876"} ) # Verify response structure @@ -215,7 +215,7 @@ class TestCallbackManagementEndpoints: # Make request to get callback configs endpoint response = client.get( - "/callbacks/configs", headers={"Authorization": "Bearer sk-1234"} + "/callbacks/configs", headers={"Authorization": "Bearer sk-9876"} ) # Verify response @@ -263,7 +263,7 @@ class TestCallbackManagementEndpoints: class TestNewRelicCallbackConfig: def test_newrelic_entry_supports_team_logging_with_dynamic_params(self): client = TestClient(app) - response = client.get("/callbacks/configs", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/callbacks/configs", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 200 newrelic = next( (config for config in response.json() if config.get("id") == "newrelic"), @@ -284,7 +284,7 @@ class TestLangfuseOtelCallbackConfig: from litellm.types.utils import OTEL_SPAN_SCOPES client = TestClient(app) - response = client.get("/callbacks/configs", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/callbacks/configs", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 200 langfuse_otel = next(config for config in response.json() if config.get("id") == "langfuse_otel") scope = langfuse_otel["dynamic_params"]["langfuse_span_scope"] diff --git a/tests/unit/proxy/management_endpoints/test_coordination_redis_endpoints.py b/tests/unit/proxy/management_endpoints/test_coordination_redis_endpoints.py index 7c6e8154107..288d8847fbb 100644 --- a/tests/unit/proxy/management_endpoints/test_coordination_redis_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_coordination_redis_endpoints.py @@ -25,6 +25,7 @@ from litellm.proxy.management_endpoints.coordination_redis_endpoints import ( from litellm.types.management_endpoints.coordination_redis_endpoints import ( COORDINATION_REDIS_SETTINGS_FIELDS, ) +from tests._master_key import MASTER_KEY _SAVED_SETTINGS = { "host": "coord-redis.example.com", @@ -275,7 +276,7 @@ async def test_update_persists_into_the_general_settings_config_row(monkeypatch) (the row startup merges over the yaml config), and sibling general_settings keys survive the write.""" monkeypatch.setattr(litellm, "store_audit_logs", False) - mock_prisma = _prisma_with_general_settings({"master_key": "sk-1234"}) + mock_prisma = _prisma_with_general_settings({"master_key": MASTER_KEY}) invalidated: list[str] = [] async def _capture_invalidate(param_name: str) -> None: @@ -306,7 +307,7 @@ async def test_update_persists_into_the_general_settings_config_row(monkeypatch) "port": 6379, "password": "pw", } - assert persisted["master_key"] == "sk-1234" + assert persisted["master_key"] == MASTER_KEY assert invalidated == ["general_settings"] # the response echoes the saved settings back redacted @@ -632,7 +633,7 @@ def _real_proxy_config(file_general_settings: dict) -> "object": @pytest.mark.asyncio async def test_update_refuses_a_config_owned_coordination_redis_block(monkeypatch): monkeypatch.setattr(litellm, "store_audit_logs", False) - mock_prisma = _prisma_with_general_settings({"master_key": "sk-1234"}) + mock_prisma = _prisma_with_general_settings({"master_key": MASTER_KEY}) from_file = {"coordination_redis": {"host": "yaml-redis.example.com", "port": 6379}} with ( @@ -655,14 +656,14 @@ async def test_update_refuses_a_config_owned_coordination_redis_block(monkeypatc @pytest.mark.asyncio async def test_update_still_persists_when_the_config_file_declares_no_block(monkeypatch): monkeypatch.setattr(litellm, "store_audit_logs", False) - mock_prisma = _prisma_with_general_settings({"master_key": "sk-1234"}) + mock_prisma = _prisma_with_general_settings({"master_key": MASTER_KEY}) async def _capture_invalidate(param_name: str) -> None: return None with ( patch("litellm.proxy.proxy_server.prisma_client", mock_prisma), # test-quality-ok: the endpoint reads these proxy_server module globals at call time; there is no injection seam - patch("litellm.proxy.proxy_server.proxy_config", _real_proxy_config({"master_key": "sk-1234"})), # test-quality-ok: the endpoint reads these proxy_server module globals at call time; there is no injection seam + patch("litellm.proxy.proxy_server.proxy_config", _real_proxy_config({"master_key": MASTER_KEY})), # test-quality-ok: the endpoint reads these proxy_server module globals at call time; there is no injection seam patch("litellm.proxy.proxy_server.store_model_in_db", True), # test-quality-ok: the endpoint reads these proxy_server module globals at call time; there is no injection seam patch( # test-quality-ok: the endpoint reads these proxy_server module globals at call time; there is no injection seam "litellm.proxy.management_endpoints.coordination_redis_endpoints.invalidate_config_param", diff --git a/tests/unit/proxy/management_endpoints/test_cost_tracking_settings.py b/tests/unit/proxy/management_endpoints/test_cost_tracking_settings.py index 94d388fce60..e155ef6fbaa 100644 --- a/tests/unit/proxy/management_endpoints/test_cost_tracking_settings.py +++ b/tests/unit/proxy/management_endpoints/test_cost_tracking_settings.py @@ -58,7 +58,7 @@ class TestCostTrackingSettings: # Make request response = client.get( "/config/cost_discount_config", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify response @@ -97,7 +97,7 @@ class TestCostTrackingSettings: # Make request response = client.get( "/config/cost_discount_config", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify response @@ -146,7 +146,7 @@ class TestCostTrackingSettings: response = client.patch( "/config/cost_discount_config", json=test_discount_config, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify response @@ -199,7 +199,7 @@ class TestCostTrackingSettings: response = client.patch( "/config/cost_discount_config", json=test_discount_config, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify response - should fail with 400 @@ -240,7 +240,7 @@ class TestCostTrackingSettings: response = client.patch( "/config/cost_discount_config", json=test_discount_config, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify response - should fail with 400 @@ -280,7 +280,7 @@ class TestCostTrackingSettings: response = client.patch( "/config/cost_discount_config", json=test_discount_config, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify response - should fail with 500 @@ -696,7 +696,7 @@ class TestBlockRequestsForModelsWithoutPricing: with patch.object(litellm, "block_requests_for_models_without_pricing", True): response = client.get( "/config/block_requests_for_models_without_pricing", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) assert response.status_code == 200 @@ -716,7 +716,7 @@ class TestBlockRequestsForModelsWithoutPricing: ): response = client.patch( "/config/block_requests_for_models_without_pricing", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, json={"enabled": True}, ) @@ -778,7 +778,7 @@ class TestBlockRequestsForModelsWithoutPricing: ): response = client.patch( "/config/block_requests_for_models_without_pricing", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, json={"enabled": True}, ) @@ -1202,7 +1202,7 @@ class TestCostEstimateRequestTokenSubsets: def test_the_endpoint_answers_422_when_cache_tokens_exceed_input_tokens(self): response = client.post( "/cost/estimate", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, json={"model": AN_ALIAS, "input_tokens": 1000, "output_tokens": 100, "cache_read_input_tokens": 8000}, ) diff --git a/tests/unit/proxy/management_endpoints/test_delete_callbacks_endpoint.py b/tests/unit/proxy/management_endpoints/test_delete_callbacks_endpoint.py index 291f3d8fe2f..6e246fb7347 100644 --- a/tests/unit/proxy/management_endpoints/test_delete_callbacks_endpoint.py +++ b/tests/unit/proxy/management_endpoints/test_delete_callbacks_endpoint.py @@ -87,7 +87,7 @@ class MockPrismaClient: def mock_auth(): """Mock admin user authentication""" return UserAPIKeyAuth( - user_id="test_admin", user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_id="test_admin", user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876" ) diff --git a/tests/unit/proxy/management_endpoints/test_gateway_request_endpoints.py b/tests/unit/proxy/management_endpoints/test_gateway_request_endpoints.py index 4f4e378bae4..24323d06d78 100644 --- a/tests/unit/proxy/management_endpoints/test_gateway_request_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_gateway_request_endpoints.py @@ -2,6 +2,8 @@ import os from datetime import datetime, timedelta, timezone from unittest.mock import AsyncMock, MagicMock, patch +from tests._master_key import MASTER_KEY + # Patching ``litellm.proxy.proxy_server.prisma_client`` imports that module, whose # module-level setup reads DATABASE_URL and LITELLM_MASTER_KEY. Tier-zero runners # set neither, so pin throwaways first, as test_component_allowlists.py does. The @@ -9,7 +11,7 @@ from unittest.mock import AsyncMock, MagicMock, patch # tests sharing the xdist worker and make them treat a phantom database as live. _THROWAWAY_ENV = { "DATABASE_URL": "sqlite:///:memory:", - "LITELLM_MASTER_KEY": "sk-test-gateway-request-endpoints", + "LITELLM_MASTER_KEY": MASTER_KEY, } _PRE_EXISTING_ENV = {key: os.environ.get(key) for key in _THROWAWAY_ENV} for _key, _value in _THROWAWAY_ENV.items(): diff --git a/tests/unit/proxy/management_endpoints/test_jwt_key_mapping.py b/tests/unit/proxy/management_endpoints/test_jwt_key_mapping.py index 50b7a5c03fd..a1f9188195a 100644 --- a/tests/unit/proxy/management_endpoints/test_jwt_key_mapping.py +++ b/tests/unit/proxy/management_endpoints/test_jwt_key_mapping.py @@ -51,12 +51,12 @@ async def test_jwt_to_virtual_key_mapping_resolution(): # Mock finding a mapping mock_mapping = MagicMock() - mock_mapping.token = "sk-1234" + mock_mapping.token = "sk-9876" mock_mapping.is_active = True prisma_client.db.litellm_jwtkeymapping.find_first.return_value = mock_mapping # Mock getting the key object - mock_key_obj = UserAPIKeyAuth(token="sk-1234", team_id="team1") + mock_key_obj = UserAPIKeyAuth(token="sk-9876", team_id="team1") user_api_key_cache = DualCache() diff --git a/tests/unit/proxy/management_endpoints/test_key_generate_prisma.py b/tests/unit/proxy/management_endpoints/test_key_generate_prisma.py index 348924b4064..a4126c476bd 100644 --- a/tests/unit/proxy/management_endpoints/test_key_generate_prisma.py +++ b/tests/unit/proxy/management_endpoints/test_key_generate_prisma.py @@ -108,6 +108,7 @@ from litellm.proxy._types import ( UpdateUserRequest, UserAPIKeyAuth, ) +from tests._master_key import MASTER_KEY proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) @@ -152,7 +153,7 @@ async def test_new_user_response(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() from litellm.proxy.proxy_server import user_api_key_cache @@ -165,7 +166,7 @@ async def test_new_user_response(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -177,7 +178,7 @@ async def test_new_user_response(prisma_client): tpm_limit=20, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -239,7 +240,7 @@ def test_generate_and_call_with_valid_key(prisma_client, api_route): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: async def test(): @@ -248,7 +249,7 @@ def test_generate_and_call_with_valid_key(prisma_client, api_route): user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ) request = NewUserRequest(user_role=LitellmUserRoles.INTERNAL_USER) @@ -300,7 +301,7 @@ def test_generate_and_call_with_valid_key(prisma_client, api_route): def test_call_with_invalid_key(prisma_client): # 2. Make a call with invalid key, expect it to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) async def test(): await litellm.proxy.proxy_server.prisma_client.connect() @@ -328,7 +329,7 @@ def test_call_with_invalid_model(prisma_client): litellm.set_verbose = True # 3. Make a call to a key with an invalid model - expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) async def test(): await litellm.proxy.proxy_server.prisma_client.connect() @@ -337,7 +338,7 @@ def test_call_with_invalid_model(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -375,7 +376,7 @@ def test_call_with_invalid_model(prisma_client): def test_call_with_valid_model(prisma_client): # 4. Make a call to a key with a valid model - expect to pass setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: async def test(): @@ -385,7 +386,7 @@ def test_call_with_valid_model(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -423,7 +424,7 @@ async def test_call_with_valid_model_using_all_models(prisma_client): """ # Make a call to a key with model = `all-proxy-models` this is an Alias from LiteLLM Admin UI setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: await litellm.proxy.proxy_server.prisma_client.connect() @@ -447,7 +448,7 @@ async def test_call_with_valid_model_using_all_models(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -485,7 +486,7 @@ async def test_call_with_valid_model_using_all_models(prisma_client): def test_call_with_user_over_budget(prisma_client): # 5. Make a call with a key over budget, expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) async def test(): await litellm.proxy.proxy_server.prisma_client.connect() @@ -494,7 +495,7 @@ def test_call_with_user_over_budget(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -578,7 +579,7 @@ def test_call_with_end_user_over_budget(prisma_client): import random setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm, "max_end_user_budget", 0.00001) async def test(): @@ -591,14 +592,14 @@ def test_call_with_end_user_over_budget(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) request = Request(scope={"type": "http"}) request._url = URL(url="/chat/completions") - bearer_token = "Bearer sk-1234" + bearer_token = "Bearer sk-9876" async def return_body(): return_string = f'{{"model": "gemini-pro-vision", "user": "{user}"}}' @@ -635,7 +636,7 @@ def test_call_with_end_user_over_budget(prisma_client): "stream": False, "litellm_params": { "metadata": { - "user_api_key": "sk-1234", + "user_api_key": MASTER_KEY, "user_api_key_end_user_id": user, }, "proxy_server_request": { @@ -680,7 +681,7 @@ def test_call_with_end_user_over_budget(prisma_client): def test_call_with_proxy_over_budget(prisma_client): # 5.1 Make a call with a proxy over budget, expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) litellm_proxy_budget_name = f"litellm-proxy-budget-{time.time()}" setattr( litellm.proxy.proxy_server, @@ -702,7 +703,7 @@ def test_call_with_proxy_over_budget(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -779,7 +780,7 @@ def test_call_with_proxy_over_budget(prisma_client): def test_call_with_user_over_budget_stream(prisma_client): # 6. Make a call with a key over budget, expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) import logging from litellm._logging import verbose_proxy_logger @@ -794,7 +795,7 @@ def test_call_with_user_over_budget_stream(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -868,7 +869,7 @@ def test_call_with_user_over_budget_stream(prisma_client): def test_call_with_proxy_over_budget_stream(prisma_client): # 6.1 Make a call with a global proxy over budget, expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) litellm_proxy_budget_name = f"litellm-proxy-budget-{time.time()}" setattr( litellm.proxy.proxy_server, @@ -901,7 +902,7 @@ def test_call_with_proxy_over_budget_stream(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -976,7 +977,7 @@ def test_generate_and_call_with_valid_key_never_expires(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: async def test(): @@ -986,7 +987,7 @@ def test_generate_and_call_with_valid_key_never_expires(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1014,7 +1015,7 @@ def test_generate_and_call_with_expired_key(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) async def test(): await litellm.proxy.proxy_server.prisma_client.connect() @@ -1023,7 +1024,7 @@ def test_generate_and_call_with_expired_key(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1056,7 +1057,7 @@ def test_delete_key(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "user_custom_auth", None) try: @@ -1069,7 +1070,7 @@ def test_delete_key(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1080,7 +1081,7 @@ def test_delete_key(prisma_client): delete_key_request = KeyRequest(keys=[generated_key]) - bearer_token = "Bearer sk-1234" + bearer_token = "Bearer sk-9876" request = Request(scope={"type": "http"}) request._url = URL(url="/key/delete") @@ -1114,7 +1115,7 @@ def test_delete_key_auth(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: async def test(): @@ -1126,7 +1127,7 @@ def test_delete_key_auth(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1138,7 +1139,7 @@ def test_delete_key_auth(prisma_client): delete_key_request = KeyRequest(keys=[generated_key]) # delete the key - bearer_token = "Bearer sk-1234" + bearer_token = "Bearer sk-9876" request = Request(scope={"type": "http"}) request._url = URL(url="/key/delete") @@ -1193,7 +1194,7 @@ def test_generate_and_call_key_info(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: async def test(): @@ -1205,7 +1206,7 @@ def test_generate_and_call_key_info(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1231,7 +1232,7 @@ def test_generate_and_call_key_info(prisma_client): # cleanup - delete key delete_key_request = KeyRequest(keys=[generated_key]) - bearer_token = "Bearer sk-1234" + bearer_token = "Bearer sk-9876" request = Request(scope={"type": "http"}) request._url = URL(url="/key/delete") @@ -1260,7 +1261,7 @@ def test_generate_and_update_key(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: async def test(): @@ -1275,7 +1276,7 @@ def test_generate_and_update_key(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), http_request=Request(scope={"type": "http"}), @@ -1288,7 +1289,7 @@ def test_generate_and_update_key(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), http_request=Request(scope={"type": "http"}), @@ -1303,7 +1304,7 @@ def test_generate_and_update_key(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1341,7 +1342,7 @@ def test_generate_and_update_key(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1354,7 +1355,7 @@ def test_generate_and_update_key(prisma_client): data=UpdateKeyRequest(key=generated_key, tpm_limit=1000), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1416,7 +1417,7 @@ def test_generate_and_update_key(prisma_client): delete_key_request = KeyRequest(keys=[generated_key]) # delete the key - bearer_token = "Bearer sk-1234" + bearer_token = "Bearer sk-9876" request = Request(scope={"type": "http"}) request._url = URL(url="/key/delete") @@ -1484,7 +1485,7 @@ def test_key_generate_with_custom_auth(prisma_client): } setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr( litellm.proxy.proxy_server, "user_custom_key_generate", custom_generate_key_fn ) @@ -1501,7 +1502,7 @@ def test_key_generate_with_custom_auth(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1522,7 +1523,7 @@ def test_key_generate_with_custom_auth(prisma_client): request_2, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1543,7 +1544,7 @@ def test_key_generate_with_custom_auth(prisma_client): def test_call_with_key_over_budget(prisma_client): # 12. Make a call with a key over budget, expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) async def test(): await litellm.proxy.proxy_server.prisma_client.connect() @@ -1552,7 +1553,7 @@ def test_call_with_key_over_budget(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1662,7 +1663,7 @@ def test_call_with_key_over_budget_no_cache(prisma_client): # ✅ Tests if spend trackign works when the key does not exist in memory # Related to this: https://github.com/BerriAI/litellm/issues/3920 setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) async def test(): await litellm.proxy.proxy_server.prisma_client.connect() @@ -1671,7 +1672,7 @@ def test_call_with_key_over_budget_no_cache(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1796,7 +1797,7 @@ async def test_aasync_call_with_key_over_model_budget( ): # 12. Make a call with a key over budget, expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "premium_user", True) await litellm.proxy.proxy_server.prisma_client.connect() verbose_proxy_logger.setLevel(logging.DEBUG) @@ -1825,7 +1826,7 @@ async def test_aasync_call_with_key_over_model_budget( request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1912,7 +1913,7 @@ async def test_aasync_call_with_key_over_model_budget( async def test_call_with_key_never_over_budget(prisma_client): # Make a call with a key with budget=None, it should never fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: await litellm.proxy.proxy_server.prisma_client.connect() request = GenerateKeyRequest(max_budget=None) @@ -1920,7 +1921,7 @@ async def test_call_with_key_never_over_budget(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -1998,7 +1999,7 @@ async def test_call_with_key_never_over_budget(prisma_client): async def test_call_with_key_over_budget_stream(prisma_client): # 14. Make a call with a key over budget, expect to fail setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) import logging from litellm._logging import verbose_proxy_logger @@ -2011,7 +2012,7 @@ async def test_call_with_key_over_budget_stream(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2087,7 +2088,7 @@ async def test_call_with_key_over_budget_stream(prisma_client): @pytest.mark.asyncio() async def test_aview_spend_per_user(prisma_client): setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() try: user_by_spend = await spend_user_fn(user_id=None) @@ -2109,7 +2110,7 @@ async def test_view_spend_per_key(prisma_client): Test viewing spend per key. """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() try: # First create a key to ensure there's data to query @@ -2118,7 +2119,7 @@ async def test_view_spend_per_key(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test_user_spend", ), ) @@ -2156,7 +2157,7 @@ async def test_key_name_null(prisma_client): - assert key_name is null """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) os.environ["DISABLE_KEY_NAME"] = "True" await litellm.proxy.proxy_server.prisma_client.connect() try: @@ -2165,7 +2166,7 @@ async def test_key_name_null(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2193,7 +2194,7 @@ async def test_key_name_set(prisma_client): - assert key_name is not null """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "general_settings", {"allow_user_auth": True}) await litellm.proxy.proxy_server.prisma_client.connect() try: @@ -2202,7 +2203,7 @@ async def test_key_name_set(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2227,7 +2228,7 @@ async def test_default_key_params(prisma_client): - assert key_name is not null """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "general_settings", {"allow_user_auth": True}) litellm.default_key_generate_params = {"max_budget": 0.000122} await litellm.proxy.proxy_server.prisma_client.connect() @@ -2237,7 +2238,7 @@ async def test_default_key_params(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2262,7 +2263,7 @@ async def test_upperbound_key_param_larger_budget(prisma_client): - assert key_name is not null """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) litellm.upperbound_key_generate_params = LiteLLM_UpperboundKeyGenerateParams( max_budget=0.001, budget_duration="1m" ) @@ -2276,7 +2277,7 @@ async def test_upperbound_key_param_larger_budget(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2287,7 +2288,7 @@ async def test_upperbound_key_param_larger_budget(prisma_client): @pytest.mark.skip(reason="Requires reliable external DB connection (prisma).") async def test_upperbound_key_param_larger_duration(prisma_client): setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) litellm.upperbound_key_generate_params = LiteLLM_UpperboundKeyGenerateParams( max_budget=100, duration="14d" ) @@ -2301,7 +2302,7 @@ async def test_upperbound_key_param_larger_duration(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2314,7 +2315,7 @@ async def test_upperbound_key_param_none_duration(prisma_client): from datetime import datetime, timedelta setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) litellm.upperbound_key_generate_params = LiteLLM_UpperboundKeyGenerateParams( max_budget=100, duration="14d" ) @@ -2325,7 +2326,7 @@ async def test_upperbound_key_param_none_duration(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2368,9 +2369,9 @@ def test_get_bearer_token(): assert result == "", f"Expected '', got '{result}'" # Test API key with Bearer prefix and no token - api_key = "Bearer sk-1234" + api_key = "Bearer sk-9876" result = _get_bearer_token(api_key) - assert result == "sk-1234", f"Expected 'valid_token', got '{result}'" + assert result == "sk-9876", f"Expected 'sk-9876', got '{result}'" @pytest.mark.asyncio @@ -2407,7 +2408,7 @@ async def test_user_api_key_auth(prisma_client): from litellm.proxy.proxy_server import ProxyException setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "general_settings", {"allow_user_auth": True}) await litellm.proxy.proxy_server.prisma_client.connect() @@ -2477,7 +2478,7 @@ async def test_key_with_no_permissions(prisma_client): - assert key_name is null """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "general_settings", {"allow_user_auth": False}) await litellm.proxy.proxy_server.prisma_client.connect() try: @@ -2552,7 +2553,7 @@ async def test_proxy_load_test_db(prisma_client): Run 1500 req./s against track_cost_callback function """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) import logging import time @@ -2568,7 +2569,7 @@ async def test_proxy_load_test_db(prisma_client): request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2617,7 +2618,7 @@ async def test_master_key_hashing(prisma_client): print("prisma client=", prisma_client) - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "master_key", master_key) @@ -2628,14 +2629,14 @@ async def test_master_key_hashing(prisma_client): _team_id = "ishaans-special-team_{}".format(uuid.uuid4()) user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ) await new_team( NewTeamRequest(team_id=_team_id), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), http_request=Request(scope={"type": "http"}), @@ -2687,7 +2688,7 @@ async def test_reset_spend_authentication(prisma_client): print("prisma client=", prisma_client) - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "master_key", master_key) @@ -2774,7 +2775,7 @@ async def test_create_update_team(prisma_client): """ print("prisma client=", prisma_client) - master_key = "sk-1234" + master_key = MASTER_KEY setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "master_key", master_key) @@ -2795,7 +2796,7 @@ async def test_create_update_team(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2824,7 +2825,7 @@ async def test_create_update_team(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2862,7 +2863,7 @@ async def test_create_update_team(prisma_client): http_request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2894,7 +2895,7 @@ async def test_update_user_role(prisma_client): -> access an Admin only route -> expect to succeed """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() key = await new_user( data=NewUserRequest( @@ -2931,7 +2932,7 @@ async def test_update_user_role(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -2953,7 +2954,7 @@ async def test_update_user_unit_test(prisma_client): Ensure that params are updated for UpdateUserRequest """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() key = await new_user( data=NewUserRequest( @@ -2975,7 +2976,7 @@ async def test_update_user_unit_test(prisma_client): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -3011,7 +3012,7 @@ async def test_update_user_unit_test(prisma_client): async def test_custom_api_key_header_name(prisma_client): """ """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr( litellm.proxy.proxy_server, "general_settings", @@ -3026,7 +3027,7 @@ async def test_custom_api_key_header_name(prisma_client): "route": api_route, "path": api_route.path, "headers": [ - (b"x-litellm-key", b"Bearer sk-1234"), + (b"x-litellm-key", b"Bearer sk-9876"), ], } ) @@ -3046,7 +3047,7 @@ async def test_custom_api_key_header_name(prisma_client): with pytest.raises( Exception, match=re.escape("Malformed API Key passed in. Ensure Key has `Bearer ` prefix") ) as exc_info: - result = await user_api_key_auth(request=request, api_key="Bearer sk-1234") + result = await user_api_key_auth(request=request, api_key="Bearer sk-9876") e = exc_info.value print("failed with error", e) assert ( @@ -3062,7 +3063,7 @@ async def test_generate_key_with_model_tpm_limit(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() request = GenerateKeyRequest( metadata={ @@ -3075,7 +3076,7 @@ async def test_generate_key_with_model_tpm_limit(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -3131,7 +3132,7 @@ async def test_generate_key_with_guardrails(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() request = GenerateKeyRequest( guardrails=["aporia-pre-call"], @@ -3143,7 +3144,7 @@ async def test_generate_key_with_guardrails(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -3201,7 +3202,7 @@ async def test_team_guardrails(prisma_client): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() _new_team = NewTeamRequest( @@ -3265,7 +3266,7 @@ async def test_team_access_groups(prisma_client): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # create router with access groups litellm_router = litellm.Router( @@ -3311,7 +3312,7 @@ async def test_team_access_groups(prisma_client): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -3370,7 +3371,7 @@ async def test_team_tags(prisma_client): """ litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() _new_team = NewTeamRequest( @@ -3430,7 +3431,7 @@ async def test_aadmin_only_routes(prisma_client): litellm.set_verbose = True print(f"os.getenv('DATABASE_URL')={os.getenv('DATABASE_URL')}") setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() general_settings = { "allowed_routes": ["/embeddings", "/key/generate"], @@ -3504,7 +3505,7 @@ async def test_list_keys(prisma_client): from litellm.proxy._types import LitellmUserRoles setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Test basic listing @@ -3641,7 +3642,7 @@ async def test_key_aliases(prisma_client): # Wire up test prisma client setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Basic call - check pagination response shape @@ -3698,15 +3699,15 @@ async def test_auth_vertex_ai_route(prisma_client): litellm.set_verbose = True setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) setattr(litellm.proxy.proxy_server, "premium_user", True) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() route = "/vertex-ai/publishers/google/models/gemini-1.5-flash-001:generateContent" request = Request(scope={"type": "http"}) request._url = URL(url=route) - request._headers = {"Authorization": "Bearer sk-12345"} + request._headers = {"Authorization": "Bearer sk-98765"} with pytest.raises(Exception, match="Invalid proxy server token passed") as exc_info: - await user_api_key_auth(request=request, api_key="Bearer " + "sk-12345") + await user_api_key_auth(request=request, api_key="Bearer " + "sk-98765") e = exc_info.value print(vars(e)) print("error str=", str(e.message)) @@ -3747,7 +3748,7 @@ async def test_user_api_key_auth_db_unavailable(monkeypatch): # Set up test environment setattr(litellm.proxy.proxy_server, "prisma_client", MockPrismaClient()) monkeypatch.setattr(litellm.proxy.proxy_server, "user_api_key_cache", MockDualCache()) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr( litellm.proxy.proxy_server, "general_settings", @@ -3761,7 +3762,7 @@ async def test_user_api_key_auth_db_unavailable(monkeypatch): # Run test with a sample API key result = await user_api_key_auth( request=request, - api_key="Bearer sk-123456789", + api_key="Bearer sk-987656789", ) from litellm.proxy.auth.auth_exception_handler import ( @@ -3809,7 +3810,7 @@ async def test_user_api_key_auth_db_unavailable_not_allowed(monkeypatch): setattr(litellm.proxy.proxy_server, "prisma_client", MockPrismaClient()) monkeypatch.setattr(litellm.proxy.proxy_server, "user_api_key_cache", MockDualCache()) setattr(litellm.proxy.proxy_server, "general_settings", {}) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) # Create test request request = Request(scope={"type": "http"}) @@ -3819,7 +3820,7 @@ async def test_user_api_key_auth_db_unavailable_not_allowed(monkeypatch): with pytest.raises(litellm.proxy._types.ProxyException): await user_api_key_auth( request=request, - api_key="Bearer sk-123456789", + api_key="Bearer sk-987656789", ) @@ -3874,7 +3875,7 @@ async def test_key_generate_with_secret_manager_call( } setattr(litellm.proxy.proxy_server, "general_settings", general_settings) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) await litellm.proxy.proxy_server.prisma_client.connect() ############################################################################ @@ -3894,7 +3895,7 @@ async def test_key_generate_with_secret_manager_call( ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -3924,7 +3925,7 @@ async def test_key_generate_with_secret_manager_call( await delete_key_fn( data=KeyRequest(keys=[generated_key]), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="1234" ), ) @@ -3956,7 +3957,7 @@ async def test_key_alias_uniqueness(prisma_client): 3. We can update a key while keeping its existing alias """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() try: @@ -3966,7 +3967,7 @@ async def test_key_alias_uniqueness(prisma_client): data=GenerateKeyRequest(key_alias=unique_alias), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -3977,7 +3978,7 @@ async def test_key_alias_uniqueness(prisma_client): data=GenerateKeyRequest(key_alias=unique_alias), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -3991,7 +3992,7 @@ async def test_key_alias_uniqueness(prisma_client): data=GenerateKeyRequest(key_alias=another_alias), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -4003,7 +4004,7 @@ async def test_key_alias_uniqueness(prisma_client): request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -4016,7 +4017,7 @@ async def test_key_alias_uniqueness(prisma_client): request=Request(scope={"type": "http"}), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -4058,7 +4059,7 @@ async def test_enforce_unique_key_alias(prisma_client): data=GenerateKeyRequest(key_alias=unique_alias), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -4084,7 +4085,7 @@ async def test_enforce_unique_key_alias(prisma_client): data=GenerateKeyRequest(key_alias=f"test-alias-{uuid.uuid4()}"), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -4131,7 +4132,7 @@ async def test_get_paginated_teams(prisma_client): from litellm.proxy.management_endpoints.team_endpoints import get_paginated_teams setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() try: @@ -4187,7 +4188,7 @@ async def test_reset_budget_job(prisma_client, entity_type): # Setup setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() proxy_logging_obj = ProxyLogging(user_api_key_cache=None) @@ -4206,7 +4207,7 @@ async def test_reset_budget_job(prisma_client, entity_type): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -4231,7 +4232,7 @@ async def test_reset_budget_job(prisma_client, entity_type): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), ) @@ -4256,7 +4257,7 @@ async def test_reset_budget_job(prisma_client, entity_type): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="1234", ), http_request=Request(scope={"type": "http"}), @@ -4332,7 +4333,7 @@ def test_delete_nonexistent_key_returns_404(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) try: async def test(): @@ -4342,7 +4343,7 @@ def test_delete_nonexistent_key_returns_404(prisma_client): random.choices(string.ascii_letters + string.digits, k=24) ) delete_key_request = KeyRequest(keys=[random_key]) - bearer_token = "Bearer sk-1234" + bearer_token = "Bearer sk-9876" request = Request(scope={"type": "http"}) request._url = URL(url="/key/delete") # use admin to auth in diff --git a/tests/unit/proxy/management_endpoints/test_key_management_endpoints.py b/tests/unit/proxy/management_endpoints/test_key_management_endpoints.py index ce8f05e879e..48ecdb287ab 100644 --- a/tests/unit/proxy/management_endpoints/test_key_management_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_key_management_endpoints.py @@ -322,7 +322,7 @@ async def test_key_token_handling(monkeypatch): response = await generate_key_fn( data=GenerateKeyRequest(), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876", user_id="1234" ), ) @@ -567,7 +567,7 @@ async def test_key_generation_with_object_permission(monkeypatch): data=request_data, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="user-1", ), ) @@ -623,7 +623,7 @@ async def test_generate_key_debug_log_never_contains_raw_token(monkeypatch, capl data=GenerateKeyRequest(key=raw_key), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="user-1", ), ) @@ -1052,7 +1052,7 @@ async def test_key_generation_with_mcp_tool_permissions(monkeypatch): data=request_data, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="user-mcp-1", ), ) @@ -1550,10 +1550,10 @@ async def test_get_new_token_rejects_short_new_key(monkeypatch): @pytest.mark.asyncio -@pytest.mark.parametrize("short_key", ["sk-1234", "sk-abcdefghijkl"]) +@pytest.mark.parametrize("short_key", ["sk-9876", "sk-abcdefghijkl"]) async def test_generate_key_fn_rejects_short_custom_key(monkeypatch, short_key): """Regression test for LIT-4355: /key/generate must reject custom keys shorter - than the minimum length (including the 15-char boundary); sk-1234 used to be + than the minimum length (including the 15-char boundary); sk-9876 used to be accepted and fully exposed via key_name.""" mock_prisma_client = AsyncMock() mock_prisma_client.db = MagicMock() @@ -1576,7 +1576,7 @@ async def test_generate_key_fn_rejects_short_custom_key(monkeypatch, short_key): await generate_key_fn( data=GenerateKeyRequest(key=short_key), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876", user_id="1234" ), ) @@ -1613,7 +1613,7 @@ async def test_generate_key_fn_accepts_custom_key_at_minimum_length(monkeypatch) response = await generate_key_fn( data=GenerateKeyRequest(key=custom_key), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876", user_id="1234" ), ) @@ -3020,7 +3020,7 @@ async def test_generate_key_rejects_a_duration_that_never_advances(monkeypatch, await generate_key_fn( data=GenerateKeyRequest(budget_duration=bad_duration), user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", user_id="1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876", user_id="1234" ), ) @@ -7411,7 +7411,7 @@ async def test_generate_key_with_router_settings(monkeypatch): data=request_data, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="user-router-1", ), ) @@ -9222,7 +9222,7 @@ async def test_key_with_budget_id_does_not_store_budget_duration(): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="admin-user", ), litellm_changed_by=None, @@ -9286,7 +9286,7 @@ async def test_key_does_not_override_explicit_budget_duration(): ), user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="admin-user", ), litellm_changed_by=None, @@ -9386,7 +9386,7 @@ async def test_rotate_master_key_reencrypts_model_params_in_place( user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="test-user", ) @@ -9472,7 +9472,7 @@ async def test_default_key_generate_params_duration(monkeypatch): data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="1234", ), litellm_changed_by=None, @@ -9533,7 +9533,7 @@ async def test_default_key_generate_params_object_permission_applied_when_absent data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="1234", ), litellm_changed_by=None, @@ -9598,7 +9598,7 @@ async def test_default_key_generate_params_object_permission_merges_partial( data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="1234", ), litellm_changed_by=None, @@ -9665,7 +9665,7 @@ async def test_default_key_generate_params_object_permission_does_not_override_e data=request, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="1234", ), litellm_changed_by=None, @@ -18541,7 +18541,7 @@ async def test_rotate_master_key_rotates_sso_identity_assertions( user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="test-user", ) @@ -18604,7 +18604,7 @@ async def test_rotate_master_key_rotates_search_tools(monkeypatch): mock_prisma_client.db.litellm_searchtoolstable.update_many = AsyncMock(side_effect=_update_many) user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="test-user", ) @@ -19297,7 +19297,7 @@ async def _generate_key_and_get_persisted_row(data: GenerateKeyRequest, mock_ins data=data, user_api_key_dict=UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key="sk-9876", user_id="1234", ), litellm_changed_by=None, diff --git a/tests/unit/proxy/management_endpoints/test_model_management_endpoints.py b/tests/unit/proxy/management_endpoints/test_model_management_endpoints.py index fae09369281..d68ff29f2f5 100644 --- a/tests/unit/proxy/management_endpoints/test_model_management_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_model_management_endpoints.py @@ -420,7 +420,7 @@ class TestModelManagementAuthChecks: assert result is True def test_can_user_attach_credential_unchanged_encrypted_existing_allows_any_role(self, monkeypatch): - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", "sk-9876") encrypted_name = encrypt_value_helper(value="shared-credential") assert encrypted_name != "shared-credential" result = ModelManagementAuthChecks.can_user_attach_credential( @@ -3408,7 +3408,7 @@ class TestUpdateDBModelKeepsLegacyDropParams: from litellm.proxy.common_utils.encrypt_decrypt_utils import decrypt_value_helper from litellm.proxy.management_endpoints.model_management_endpoints import update_db_model - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", "sk-9876") legacy_row = Deployment( model_name="gpt-5-nano", litellm_params=LiteLLM_Params( @@ -4351,7 +4351,7 @@ class TestModelInfoCostMapEchoFilter: from litellm.proxy.management_endpoints.model_management_endpoints import update_db_model from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", "sk-9876") entry = litellm.get_model_info("openai/gpt-5.6") db_model = Deployment( model_name="gpt-5.6", @@ -9090,7 +9090,7 @@ class TestWifBoundaryReadsTheResultingDeployment: credential, and lets the write through.""" from litellm.proxy.management_endpoints.model_management_endpoints import patch_model - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", "sk-9876") non_admin = UserAPIKeyAuth(user_id="team_admin", user_role=LitellmUserRoles.INTERNAL_USER) federated_row = MagicMock() federated_row.litellm_params = { diff --git a/tests/unit/proxy/management_endpoints/test_router_settings_endpoints.py b/tests/unit/proxy/management_endpoints/test_router_settings_endpoints.py index ec1af0518c6..d652d73ab49 100644 --- a/tests/unit/proxy/management_endpoints/test_router_settings_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_router_settings_endpoints.py @@ -46,7 +46,7 @@ class TestRouterSettingsEndpoints: """ # Make request to router fields endpoint response = client.get( - "/router/fields", headers={"Authorization": "Bearer sk-1234"} + "/router/fields", headers={"Authorization": "Bearer sk-9876"} ) # Verify response diff --git a/tests/unit/proxy/management_endpoints/test_tag_management_endpoints.py b/tests/unit/proxy/management_endpoints/test_tag_management_endpoints.py index d5dbd3df6a6..1dfababae55 100644 --- a/tests/unit/proxy/management_endpoints/test_tag_management_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_tag_management_endpoints.py @@ -116,7 +116,7 @@ async def test_create_and_get_tag(): "models": ["model-1"], } - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} # Test tag creation response = client.post("/tag/new", json=tag_data, headers=headers) @@ -215,7 +215,7 @@ async def test_update_tag(): "models": ["model-1", "model-2"], } - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} # Test tag update response = client.post("/tag/update", json=update_data, headers=headers) @@ -448,7 +448,7 @@ async def test_delete_tag(): # Delete tag data delete_data = {"name": "test-tag"} - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} # Test tag deletion response = client.post("/tag/delete", json=delete_data, headers=headers) @@ -544,7 +544,7 @@ async def test_new_tag_invalidates_tag_and_registry_caches(): response = client.post( "/tag/new", json={"name": "cache-tag"}, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) assert response.status_code == 200 @@ -599,7 +599,7 @@ async def test_update_tag_invalidates_only_the_tag_cache(): response = client.post( "/tag/update", json={"name": "cache-tag", "description": "updated"}, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) assert response.status_code == 200 @@ -637,7 +637,7 @@ async def test_delete_tag_invalidates_tag_and_registry_caches(): response = client.post( "/tag/delete", json={"name": "cache-tag"}, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) assert response.status_code == 200 @@ -704,7 +704,7 @@ async def test_list_tags_with_dynamic_tags(): ] ) - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} response = client.get("/tag/list", headers=headers) assert response.status_code == 200 @@ -765,7 +765,7 @@ async def test_list_tags_no_dynamic_tags(): mock_db.litellm_dailytagspend.group_by = AsyncMock(return_value=[]) - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} response = client.get("/tag/list", headers=headers) assert response.status_code == 200 @@ -936,7 +936,7 @@ async def test_list_tags_with_date_range_filters_dynamic_tags(): group_by_mock = AsyncMock(return_value=[]) mock_db.litellm_dailytagspend.group_by = group_by_mock - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} response = client.get( "/tag/list?start_date=2026-04-01&end_date=2026-04-29", headers=headers, @@ -1178,7 +1178,7 @@ async def test_list_tags_without_date_range_omits_date_filter(): group_by_mock = AsyncMock(return_value=[]) mock_db.litellm_dailytagspend.group_by = group_by_mock - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} response = client.get("/tag/list", headers=headers) assert response.status_code == 200 @@ -1218,7 +1218,7 @@ async def test_list_tags_rejects_invalid_date_range(query, expected_detail_fragm mock_db.litellm_tagtable.find_many = AsyncMock(return_value=[]) mock_db.litellm_dailytagspend.group_by = AsyncMock(return_value=[]) - headers = {"Authorization": "Bearer sk-1234"} + headers = {"Authorization": "Bearer sk-9876"} response = client.get(f"/tag/list{query}", headers=headers) assert response.status_code == 400 diff --git a/tests/unit/proxy/management_endpoints/test_team_default_params.py b/tests/unit/proxy/management_endpoints/test_team_default_params.py index 17cb30dd07d..cf4961dc82b 100644 --- a/tests/unit/proxy/management_endpoints/test_team_default_params.py +++ b/tests/unit/proxy/management_endpoints/test_team_default_params.py @@ -651,7 +651,7 @@ class TestBulkUpdateTeamMemberPermissions: return UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN.value, - api_key="sk-1234", + api_key="sk-9876", ) def _non_admin_key_dict(self): diff --git a/tests/unit/proxy/management_endpoints/test_team_endpoints.py b/tests/unit/proxy/management_endpoints/test_team_endpoints.py index 0c71ee72f2b..6f6dbe1e954 100644 --- a/tests/unit/proxy/management_endpoints/test_team_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_team_endpoints.py @@ -80,6 +80,7 @@ from litellm.types.proxy.management_endpoints.team_endpoints import ( TeamMemberAddResult, ) from litellm.types.utils import StandardAuditLogPayload +from tests._master_key import MASTER_KEY from tests.unit.proxy.management_endpoints.jwt_key_mapping_doubles import ( CascadingJWTMappingTable, JWTMappingRow, @@ -11759,7 +11760,7 @@ async def test_clear_team_member_budget_duration_calls_update_budget(): mock_user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin-user", ) @@ -11807,7 +11808,7 @@ async def test_clear_team_member_budget_clears_max_budget(): mock_user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin-user", ) @@ -11853,7 +11854,7 @@ async def test_clear_team_member_rpm_tpm_limits(): mock_user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin-user", ) @@ -11903,7 +11904,7 @@ async def test_clear_all_team_member_fields_at_once(): mock_user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin-user", ) @@ -11990,7 +11991,7 @@ async def test_clear_team_member_budget_fields_no_budget_row_skips_update(): mock_user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="admin-user", ) @@ -13174,7 +13175,7 @@ def test_get_team_metadata_schema_route_requires_auth(): parse_team_metadata_schema, ) - with patch("litellm.proxy.proxy_server.master_key", "sk-1234"): + with patch("litellm.proxy.proxy_server.master_key", MASTER_KEY): response = client.get("/team/metadata_schema") assert response.status_code == 401 diff --git a/tests/unit/proxy/management_endpoints/test_ui_sso.py b/tests/unit/proxy/management_endpoints/test_ui_sso.py index 65426b8d9cb..e053c4c94ea 100644 --- a/tests/unit/proxy/management_endpoints/test_ui_sso.py +++ b/tests/unit/proxy/management_endpoints/test_ui_sso.py @@ -33,6 +33,7 @@ from litellm.types.proxy.management_endpoints.ui_sso import ( MicrosoftServicePrincipalTeam, TeamMappings, ) +from tests._master_key import MASTER_KEY _SSO_PROVIDER_ENV_VARS = ( "DISABLE_ADMIN_UI", @@ -8525,7 +8526,7 @@ async def _render_legacy_login_page(env_overrides, general_settings): with ( # snapshot os.environ so the mutations below are reverted on exit patch.dict(os.environ, {}, clear=False), - patch("litellm.proxy.proxy_server.master_key", "sk-1234"), + patch("litellm.proxy.proxy_server.master_key", MASTER_KEY), patch("litellm.proxy.proxy_server.prisma_client", MagicMock()), patch("litellm.proxy.proxy_server.premium_user", False), patch("litellm.proxy.proxy_server.general_settings", general_settings), @@ -8656,7 +8657,7 @@ async def test_saml_callback_enforces_free_sso_user_limit_after_validation(): with patch.dict(os.environ, {"DISABLE_ADMIN_UI": "false"}), patch( "litellm.proxy.proxy_server.premium_user", False ), patch("litellm.proxy.proxy_server.prisma_client", MagicMock()), patch( - "litellm.proxy.proxy_server.master_key", "sk-1234" + "litellm.proxy.proxy_server.master_key", MASTER_KEY ), patch( "litellm.proxy.management_endpoints.sso.saml_sso.SAMLAuthHandler.handle_acs", new=_fake_handle_acs, @@ -9697,7 +9698,7 @@ async def _sso_key_generate_on_ui_disabled_node(*, source, key, google_sso_confi patch.dict(os.environ, env, clear=True), patch("litellm.proxy.proxy_server.premium_user", True), patch("litellm.proxy.proxy_server.prisma_client", MagicMock()), - patch("litellm.proxy.proxy_server.master_key", "sk-1234"), + patch("litellm.proxy.proxy_server.master_key", MASTER_KEY), patch("litellm.proxy.proxy_server.general_settings", {}), patch("litellm.proxy.proxy_server.user_api_key_cache", MagicMock()), patch("litellm.proxy.proxy_server.cli_sso_session_cache", cli_cache), diff --git a/tests/unit/proxy/management_helpers/test_audit_logs_proxy.py b/tests/unit/proxy/management_helpers/test_audit_logs_proxy.py index 98922801296..1ea608cfc17 100644 --- a/tests/unit/proxy/management_helpers/test_audit_logs_proxy.py +++ b/tests/unit/proxy/management_helpers/test_audit_logs_proxy.py @@ -46,6 +46,7 @@ from unittest.mock import patch, AsyncMock proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) import json +from tests._master_key import MASTER_KEY def test_get_audit_log_changed_by_prefers_authenticated_user(): @@ -227,7 +228,7 @@ async def test_create_audit_log_in_db(prisma_client): print("prisma client=", prisma_client) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "premium_user", True) setattr(litellm, "store_audit_logs", True) diff --git a/tests/unit/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py b/tests/unit/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py index 52ebc3a881d..24ea1fe8d53 100644 --- a/tests/unit/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py +++ b/tests/unit/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py @@ -23,6 +23,7 @@ from starlette.datastructures import FormData import litellm +from tests._master_key import MASTER_KEY as SHARED_MASTER_KEY from litellm.caching.caching import DualCache from litellm.types.utils import CallTypesLiteral from litellm.proxy.common_request_processing import ProxyBaseLLMRequestProcessing @@ -566,7 +567,7 @@ class TestVertexAIPassThroughHandler: "litellm.proxy.pass_through_endpoints.llm_passthrough_endpoints.passthrough_endpoint_router", pass_through_router, ) - monkeypatch.setattr("litellm.proxy.proxy_server.master_key", "sk-master-1234") + monkeypatch.setattr("litellm.proxy.proxy_server.master_key", SHARED_MASTER_KEY) endpoint = f"/v1/projects/{test_project}/locations/{test_location}/publishers/google/models/gemini-1.5-flash:generateContent" @@ -1880,7 +1881,7 @@ class TestBedrockAgentRuntimePassthroughToggle: class TestBedrockAgentRuntimePassthroughVirtualKeyLeak: VKEY: Final = "sk-litellm-victim-key" - MASTER_KEY: Final = "sk-master-1234" + MASTER_KEY: Final = SHARED_MASTER_KEY ENDPOINT: Final = "knowledgebases/KB1234567/retrieve" AMBIENT_AWS_ENV: Final = ( "AWS_BEARER_TOKEN_BEDROCK", @@ -3864,6 +3865,7 @@ class TestVertexCredentiallessPassthroughVirtualKeyLeak: """ VKEY = "sk-litellm-victim-key" + MASTER_KEY: Final = SHARED_MASTER_KEY ENDPOINT = "v1/projects/my-proj/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent" async def _run( @@ -3871,7 +3873,7 @@ class TestVertexCredentiallessPassthroughVirtualKeyLeak: monkeypatch, headers: list[tuple[bytes, bytes]], authenticated: UserAPIKeyAuth | None = None, - master_key: str | None = "sk-master-1234", + master_key: str | None = SHARED_MASTER_KEY, ) -> tuple[HTTPException | None, dict | None]: monkeypatch.setattr("litellm.proxy.proxy_server.master_key", master_key) caller: Final = authenticated if authenticated is not None else UserAPIKeyAuth(api_key=self.VKEY) @@ -4189,12 +4191,12 @@ class TestVertexCredentiallessPassthroughVirtualKeyLeak: ("master_key", "authenticated"), [ pytest.param( - "sk-master-1234", + SHARED_MASTER_KEY, UserAPIKeyAuth(api_key="best-api-key-ever", user_role=LitellmUserRoles.PROXY_ADMIN), id="custom-auth-returning-its-own-identifier", ), pytest.param( - "sk-master-1234", + SHARED_MASTER_KEY, UserAPIKeyAuth(api_key=None, user_id="jwt-subject", jwt_claims=dict(LITELLM_JWT_CLAIMS)), id="jwt-auth", ), @@ -4278,7 +4280,10 @@ class TestVertexCredentiallessPassthroughVirtualKeyLeak: async def test_master_key_in_authorization_alone_is_rejected(self, monkeypatch): raised, forwarded = await self._run( monkeypatch, - [(b"authorization", b"Bearer sk-master-1234"), (b"content-type", b"application/json")], + [ + (b"authorization", f"Bearer {self.MASTER_KEY}".encode()), + (b"content-type", b"application/json"), + ], authenticated=UserAPIKeyAuth(api_key=LITELLM_PROXY_MASTER_KEY_ALIAS, user_role=LitellmUserRoles.PROXY_ADMIN), ) assert forwarded is None, "the master key must never reach the upstream forwarder" @@ -4289,7 +4294,7 @@ class TestVertexCredentiallessPassthroughVirtualKeyLeak: raised, forwarded = await self._run( monkeypatch, [ - (b"authorization", b"Bearer sk-master-1234"), + (b"authorization", f"Bearer {self.MASTER_KEY}".encode()), (b"x-goog-api-key", b"AIza-real-google-api-key"), (b"content-type", b"application/json"), ], @@ -4299,7 +4304,7 @@ class TestVertexCredentiallessPassthroughVirtualKeyLeak: assert forwarded is not None assert forwarded.get("x-goog-api-key") == "AIza-real-google-api-key" assert "authorization" not in forwarded - assert "sk-master-1234" not in " ".join(f"{name}:{value}" for name, value in forwarded.items()) + assert self.MASTER_KEY not in " ".join(f"{name}:{value}" for name, value in forwarded.items()) class TestAnthropicPassthroughVirtualKeyLeak: @@ -4312,7 +4317,7 @@ class TestAnthropicPassthroughVirtualKeyLeak: monkeypatch, headers: list[tuple[bytes, bytes]], authenticated: UserAPIKeyAuth | None = None, - master_key: str | None = "sk-master-1234", + master_key: str | None = SHARED_MASTER_KEY, proxy_api_key: str | None = None, ) -> tuple[HTTPException | None, dict | None]: from litellm.proxy.pass_through_endpoints.pass_through_endpoints import HttpPassThroughEndpointHelpers @@ -4410,8 +4415,11 @@ class TestAnthropicPassthroughVirtualKeyLeak: async def test_master_key_in_authorization_is_rejected_not_forwarded(self, monkeypatch): raised, forwarded = await self._run( monkeypatch, - [(b"authorization", b"Bearer sk-master-1234"), (b"content-type", b"application/json")], - authenticated=UserAPIKeyAuth(api_key="sk-master-1234", user_role=LitellmUserRoles.PROXY_ADMIN), + [ + (b"authorization", f"Bearer {SHARED_MASTER_KEY}".encode()), + (b"content-type", b"application/json"), + ], + authenticated=UserAPIKeyAuth(api_key=SHARED_MASTER_KEY, user_role=LitellmUserRoles.PROXY_ADMIN), ) assert forwarded is None, "the master key must never reach Anthropic" assert raised is not None and raised.status_code == 401 diff --git a/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py b/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py index 31321254d94..b62f3765195 100644 --- a/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py +++ b/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py @@ -57,6 +57,7 @@ from litellm.types.passthrough_endpoints.pass_through_endpoints import ( LITELLM_PASS_THROUGH_DEPLOYMENT_MODEL_INFO_STATE_KEY, LITELLM_PASS_THROUGH_RAW_BODY_STATE_KEY, ) +from tests._master_key import MASTER_KEY MESSAGE_START_SSE_FRAME = b'event: message_start\ndata: {"type": "message_start"}\n\n' @@ -287,7 +288,7 @@ async def test_make_multipart_http_request_removes_content_type_header(): original_headers = { "content-type": "multipart/form-data; boundary=--------------------------416423083260054165225918", "user-agent": "PostmanRuntime/7.49.0", - "Authorization": "bearer sk-1234", + "Authorization": "bearer sk-9876", } # Test the function @@ -311,7 +312,7 @@ async def test_make_multipart_http_request_removes_content_type_header(): # Other headers should be preserved assert call_args["headers"]["user-agent"] == "PostmanRuntime/7.49.0" - assert call_args["headers"]["Authorization"] == "bearer sk-1234" + assert call_args["headers"]["Authorization"] == "bearer sk-9876" # Verify other parameters are correct assert call_args["method"] == "POST" @@ -2519,7 +2520,7 @@ async def test_pass_through_request_query_params_forwarding(): # Create mock user API key dict mock_user_api_key_dict = MagicMock() - mock_user_api_key_dict.api_key = "sk-1234" + mock_user_api_key_dict.api_key = MASTER_KEY # Call pass_through_request await pass_through_request( diff --git a/tests/unit/proxy/pass_through_endpoints/test_passthrough_auth_default.py b/tests/unit/proxy/pass_through_endpoints/test_passthrough_auth_default.py index 5da08e6af75..0e337195bb8 100644 --- a/tests/unit/proxy/pass_through_endpoints/test_passthrough_auth_default.py +++ b/tests/unit/proxy/pass_through_endpoints/test_passthrough_auth_default.py @@ -105,14 +105,14 @@ async def test_runtime_check_treats_missing_auth_key_as_authenticated(): request=request, route="/forwarder", pass_through_endpoints=[raw_endpoint_no_auth_key], - api_key="sk-1234", + api_key="sk-9876", ) # Result is the api_key string (auth is REQUIRED for this endpoint # — flow continues to normal key validation), NOT an empty # ``UserAPIKeyAuth()`` (which was the unauthenticated-forwarder # bug). - assert result == "sk-1234" + assert result == "sk-9876" @pytest.mark.asyncio diff --git a/tests/unit/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py b/tests/unit/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py index d6b69c7c010..2922790ea37 100644 --- a/tests/unit/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py +++ b/tests/unit/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py @@ -530,7 +530,7 @@ def test_forward_headers_from_request_x_pass_prefix(): "x-pass-custom-header": "custom-value", "x-pass-another-header": "another-value", "authorization": "Bearer sk-litellm-key", - "x-litellm-api-key": "sk-1234", + "x-litellm-api-key": "sk-9876", "content-type": "application/json", } diff --git a/tests/unit/proxy/prompts/test_prompt_endpoints_crud.py b/tests/unit/proxy/prompts/test_prompt_endpoints_crud.py index 387448bb9b3..4eca4a09016 100644 --- a/tests/unit/proxy/prompts/test_prompt_endpoints_crud.py +++ b/tests/unit/proxy/prompts/test_prompt_endpoints_crud.py @@ -41,7 +41,7 @@ async def test_delete_prompt_success(): # Mock user auth mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) # Mock DB Client @@ -96,7 +96,7 @@ async def test_delete_prompt_by_base_id_success(): # Mock user auth mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) # Mock DB Client @@ -144,7 +144,7 @@ async def test_delete_prompt_by_base_id_success(): async def test_delete_prompt_environment_scope_reaches_db_and_registry(): from litellm.proxy.prompts.prompt_endpoints import delete_prompt - mock_user_auth = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + mock_user_auth = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) mock_prisma_client = MagicMock() mock_prisma_client.db.litellm_prompttable.delete_many = AsyncMock(return_value=None) @@ -181,7 +181,7 @@ async def test_get_prompt_info_by_base_id(): # Mock user auth mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) # Mock In-Memory Registry @@ -226,7 +226,7 @@ async def test_patch_prompt_row_deleted_mid_update_returns_404(): from litellm.proxy.prompts.prompt_endpoints import PatchPromptRequest, patch_prompt mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) target_row = _db_row("Begin every reply with AHOY") @@ -271,7 +271,7 @@ async def test_patch_prompt_row_deleted_mid_update_returns_404(): async def test_patch_prompt_merges_unsent_fields_from_db_row_not_stale_memory(): from litellm.proxy.prompts.prompt_endpoints import PatchPromptRequest, patch_prompt - mock_user_auth = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + mock_user_auth = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) db_row = _db_row("Begin every reply with HOWDY") mock_prisma_client = MagicMock() mock_prisma_client.db.litellm_prompttable.find_many = AsyncMock(return_value=[db_row]) @@ -351,7 +351,7 @@ async def test_create_prompt_rejects_keyed_prompt_data_with_prompt_id(): ) mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) request = Prompt( prompt_id="agent-prompt", @@ -381,7 +381,7 @@ async def test_patch_prompt_rejects_keyed_prompt_data_with_prompt_id(): ) mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) request = PatchPromptRequest( litellm_params=PromptLiteLLMParams( @@ -408,7 +408,7 @@ async def test_patch_prompt_info_only_keeps_legacy_keyed_row_patchable(): from litellm.proxy.prompts.prompt_endpoints import PatchPromptRequest, patch_prompt mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) legacy_params = PromptLiteLLMParams( prompt_id="agent-prompt", @@ -481,7 +481,7 @@ async def test_update_prompt_rejects_keyed_prompt_data_with_prompt_id(): ) mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN ) request = Prompt( prompt_id="agent-prompt", diff --git a/tests/unit/proxy/prompts/test_prompt_environment.py b/tests/unit/proxy/prompts/test_prompt_environment.py index 3cb647dea13..00d47e444b9 100644 --- a/tests/unit/proxy/prompts/test_prompt_environment.py +++ b/tests/unit/proxy/prompts/test_prompt_environment.py @@ -83,7 +83,7 @@ async def test_create_prompt_stores_environment_and_created_by(): from litellm.proxy.prompts.prompt_endpoints import create_prompt, Prompt mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN, user_id="user-789", ) @@ -146,7 +146,7 @@ async def test_update_prompt_stores_environment_and_created_by(): from litellm.proxy.prompts.prompt_endpoints import update_prompt, Prompt mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN, user_id="user-update", ) @@ -217,7 +217,7 @@ async def test_delete_prompt_scoped_to_environment(): from litellm.proxy.prompts.prompt_endpoints import delete_prompt mock_user_auth = UserAPIKeyAuth( - api_key="sk-1234", + api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN, ) diff --git a/tests/unit/proxy/proxy_server/test_proxy_config.py b/tests/unit/proxy/proxy_server/test_proxy_config.py index c8979a07b40..2f5eb81bec8 100644 --- a/tests/unit/proxy/proxy_server/test_proxy_config.py +++ b/tests/unit/proxy/proxy_server/test_proxy_config.py @@ -43,6 +43,7 @@ from litellm.proxy.proxy_server import ( from litellm.tracing.config import trace_storage_config from .conftest import normalize +from tests._master_key import MASTER_KEY @pytest.mark.asyncio @@ -1564,7 +1565,7 @@ async def test_ProxyConfig_get_config_from_a_bucket_merges_includes(monkeypatch) objects = { "lit6982/config.yaml": { "include": ["model_config.yaml"], - "general_settings": {"master_key": "sk-1234"}, + "general_settings": {"master_key": MASTER_KEY}, }, "lit6982/model_config.yaml": {"model_list": [{"model_name": "included-model"}]}, } @@ -3221,7 +3222,7 @@ def test_ProxyConfig__add_deployment_resolves_env_refs_on_arbitrary_field(monkey ["true", "os.environ/DROP_PARAMS_FLAG"], ) def test_ProxyConfig__add_deployment_turns_stored_drop_params_string_into_bool(monkeypatch, stored_drop_params): - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", MASTER_KEY) monkeypatch.setenv("DROP_PARAMS_FLAG", "true") fake_router = MagicMock() fake_router.upsert_deployment = MagicMock(return_value=True) @@ -3246,7 +3247,7 @@ def test_ProxyConfig__add_deployment_turns_stored_drop_params_string_into_bool(m def test_ProxyConfig__add_deployment_keeps_loading_rows_after_a_non_flag_drop_params(monkeypatch): - monkeypatch.setenv("LITELLM_SALT_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_SALT_KEY", MASTER_KEY) fake_router = MagicMock() fake_router.upsert_deployment = MagicMock(return_value=True) monkeypatch.setattr("litellm.proxy.proxy_server.llm_router", fake_router) diff --git a/tests/unit/proxy/public_endpoints/public_v1/test_model_hub.py b/tests/unit/proxy/public_endpoints/public_v1/test_model_hub.py index de2d95e9f28..4267cdbbcc9 100644 --- a/tests/unit/proxy/public_endpoints/public_v1/test_model_hub.py +++ b/tests/unit/proxy/public_endpoints/public_v1/test_model_hub.py @@ -11,6 +11,7 @@ import litellm from litellm.proxy._types import LiteLLMRoutes from litellm.proxy.proxy_server import app from litellm.types.router import ModelGroupInfo +from tests._master_key import MASTER_KEY client = TestClient(app) @@ -274,7 +275,7 @@ def test_the_search_matches_model_group_names_case_insensitively(monkeypatch): @pytest.fixture def guarded(monkeypatch): """A proxy with a master key set, so anything but a public route would demand credentials.""" - monkeypatch.setattr("litellm.proxy.proxy_server.master_key", "sk-1234") + monkeypatch.setattr("litellm.proxy.proxy_server.master_key", MASTER_KEY) monkeypatch.setattr("litellm.proxy.proxy_server.general_settings", {}) diff --git a/tests/unit/proxy/response_api_endpoints/test_endpoints.py b/tests/unit/proxy/response_api_endpoints/test_endpoints.py index 656dc33e88c..456c3609419 100644 --- a/tests/unit/proxy/response_api_endpoints/test_endpoints.py +++ b/tests/unit/proxy/response_api_endpoints/test_endpoints.py @@ -16,6 +16,7 @@ from httpx import Response import litellm from litellm.proxy.proxy_server import app from litellm.types.llms.openai import ResponsesAPIResponse +from tests._master_key import MASTER_KEY @pytest.mark.asyncio @@ -290,7 +291,7 @@ class TestResponsesAPIEndpoints(unittest.TestCase): response = client.post( "/openai/v1/responses", json=test_data, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) assert response.status_code in [200, 401, 500] @@ -342,7 +343,7 @@ class TestResponsesAPIEndpoints(unittest.TestCase): response = client.post( "/cursor/chat/completions", json=test_data, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Should return 200 (or 401/500 if auth fails) @@ -1411,7 +1412,7 @@ class TestCursorMessagesArmToolNormalization: seen["body"] = await _read_request_body(request=request) return {"id": "chatcmpl-fake", "object": "chat.completion", "choices": []} - app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key="sk-1234") + app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key=MASTER_KEY) try: with patch("litellm.proxy.proxy_server.chat_completion", new=fake_chat_completion): client = TestClient(app) @@ -1438,7 +1439,7 @@ class TestCursorMessagesArmToolNormalization: ], "tool_choice": {"type": "custom", "name": "ApplyPatch"}, }, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) finally: app.dependency_overrides.pop(user_api_key_auth, None) @@ -1479,14 +1480,14 @@ class TestCursorMessagesArmToolNormalization: "messages": [{"role": "user", "content": "hi"}], "tools": [{"type": "function", "function": {"name": "f", "parameters": {}}}], } - app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key="sk-1234") + app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key=MASTER_KEY) try: with patch("litellm.proxy.proxy_server.chat_completion", new=fake_chat_completion): client = TestClient(app) response = client.post( "/cursor/chat/completions", json=body, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) finally: app.dependency_overrides.pop(user_api_key_auth, None) @@ -1686,7 +1687,7 @@ class TestCursorInputArmFlattening: ], ) - app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key="sk-1234") + app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key=MASTER_KEY) try: with patch("litellm.proxy.proxy_server.llm_router") as mock_router: mock_router.aresponses = AsyncMock(return_value=mock_response) @@ -1711,7 +1712,7 @@ class TestCursorInputArmFlattening: ], "tool_choice": {"type": "custom", "custom": {"name": "ApplyPatch"}}, }, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) finally: app.dependency_overrides.pop(user_api_key_auth, None) @@ -1766,7 +1767,7 @@ class TestChatCompletionsBodyDetection: ], ) - app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key="sk-1234") + app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key=MASTER_KEY) try: with patch("litellm.proxy.proxy_server.llm_router") as mock_router: mock_router.aresponses = AsyncMock(return_value=mock_response) @@ -1778,7 +1779,7 @@ class TestChatCompletionsBodyDetection: "messages": None, "input": [{"role": "user", "content": "hello"}], }, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) finally: app.dependency_overrides.pop(user_api_key_auth, None) @@ -1953,7 +1954,7 @@ class TestCursorModelSuffixResolutionEndToEnd: seen["body"] = await _read_request_body(request=request) return {"id": "chatcmpl-fake", "object": "chat.completion", "choices": []} - app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key="sk-1234") + app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key=MASTER_KEY) try: with ( patch("litellm.proxy.proxy_server.llm_router", new=_router_serving_only("claude-opus-5")), @@ -1966,7 +1967,7 @@ class TestCursorModelSuffixResolutionEndToEnd: "model": "claude-opus-5-thinking-xhigh-fast", "messages": [{"role": "user", "content": "hi"}], }, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) finally: app.dependency_overrides.pop(user_api_key_auth, None) @@ -2003,7 +2004,7 @@ class TestCursorModelSuffixResolutionEndToEnd: mock_router = _router_serving_only("claude-opus-5") mock_router.aresponses = AsyncMock(return_value=mock_response) - app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key="sk-1234") + app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth(api_key=MASTER_KEY) try: with patch("litellm.proxy.proxy_server.llm_router", new=mock_router): client = TestClient(app) @@ -2013,7 +2014,7 @@ class TestCursorModelSuffixResolutionEndToEnd: "model": "claude-opus-5-thinking-high", "input": [{"role": "user", "content": "hello"}], }, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) finally: app.dependency_overrides.pop(user_api_key_auth, None) @@ -2230,7 +2231,7 @@ def _post_blocked_responses( patch("litellm.proxy.proxy_server.proxy_logging_obj", mock_proxy_logging), ): client = TestClient(app) - return client.post("/v1/responses", json=body, headers={"Authorization": "Bearer sk-1234"}) + return client.post("/v1/responses", json=body, headers={"Authorization": "Bearer sk-9876"}) finally: app.dependency_overrides.pop(user_api_key_auth, None) @@ -2337,7 +2338,7 @@ class TestResponsesInputTokens: app.dependency_overrides[_proxy_token_counter] = lambda: token_counter_mock try: client = TestClient(app) - response = client.post(path, json=body, headers={"Authorization": "Bearer sk-1234"}) + response = client.post(path, json=body, headers={"Authorization": "Bearer sk-9876"}) return response, token_counter_mock finally: app.dependency_overrides.pop(user_api_key_auth, None) diff --git a/tests/unit/proxy/spend_tracking/test_search_api_logging.py b/tests/unit/proxy/spend_tracking/test_search_api_logging.py index 5a833d37615..92108f19c8e 100644 --- a/tests/unit/proxy/spend_tracking/test_search_api_logging.py +++ b/tests/unit/proxy/spend_tracking/test_search_api_logging.py @@ -22,6 +22,7 @@ from litellm.proxy.hooks.proxy_track_cost_callback import _ProxyDBLogger from litellm.proxy.spend_tracking.spend_management_endpoints import view_spend_logs from litellm.proxy.utils import ProxyLogging, hash_token, update_spend from litellm.llms.base_llm.search.transformation import SearchResponse, SearchResult +from tests._master_key import MASTER_KEY @pytest.fixture @@ -66,7 +67,7 @@ async def test_search_api_logging_and_cost_tracking(prisma_client): 6. spend is calculated and logged """ setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() # Setup router with search tool @@ -95,7 +96,7 @@ async def test_search_api_logging_and_cost_tracking(prisma_client): user_api_key_dict = UserAPIKeyAuth( user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, user_id="test_user", ) diff --git a/tests/unit/proxy/spend_tracking/test_spend_tracking_utils.py b/tests/unit/proxy/spend_tracking/test_spend_tracking_utils.py index a3de9328437..777121c219b 100644 --- a/tests/unit/proxy/spend_tracking/test_spend_tracking_utils.py +++ b/tests/unit/proxy/spend_tracking/test_spend_tracking_utils.py @@ -3402,7 +3402,7 @@ def test_redact_logged_api_key_empty_string_returns_none(): def test_redact_logged_api_key_sk_key_is_hashed(): - raw = "sk-1234secret" + raw = "sk-9876secret" result = _redact_logged_api_key(raw) assert result == hash_token(raw) assert result is not None @@ -3411,14 +3411,14 @@ def test_redact_logged_api_key_sk_key_is_hashed(): def test_redact_logged_api_key_bearer_sk_equals_sk_hash(): - raw = "sk-1234secret" + raw = "sk-9876secret" result_plain = _redact_logged_api_key(raw) result_bearer = _redact_logged_api_key(f"Bearer {raw}") assert result_bearer == result_plain def test_redact_logged_api_key_bearer_case_insensitive(): - raw = "sk-1234secret" + raw = "sk-9876secret" result_lower = _redact_logged_api_key(f"bearer {raw}") result_upper = _redact_logged_api_key(f"BEARER {raw}") expected = hash_token(raw) @@ -3618,7 +3618,7 @@ def test_redact_logged_api_key_bearer_only_returns_none(): def test_get_spend_logs_metadata_sk_key_hashed(): - raw = "sk-1234secret" + raw = "sk-9876secret" meta = _get_spend_logs_metadata({"user_api_key": raw}) assert meta["user_api_key"] == hash_token(raw) assert meta["user_api_key"] is not None @@ -3629,7 +3629,7 @@ def test_get_spend_logs_metadata_sk_key_hashed(): def test_get_spend_logs_metadata_bearer_sk_key_hashed_same_as_plain(): - raw = "sk-1234secret" + raw = "sk-9876secret" meta_plain = _get_spend_logs_metadata({"user_api_key": raw}) meta_bearer = _get_spend_logs_metadata({"user_api_key": f"Bearer {raw}"}) assert meta_bearer["user_api_key"] == meta_plain["user_api_key"] @@ -4124,7 +4124,7 @@ async def test_compression_savings_survive_to_spend_log_payload_metadata(monkeyp "max_tokens": 512, "litellm_call_id": "test-compression-call-id", "litellm_metadata": { - "user_api_key": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "user_api_key": "bc46df66218d24bc910f7c95ef9d861c706d22a191f9e7378f8a51f54146474f", "user_api_key_user_id": "u1", "user_api_key_team_id": "t1", }, diff --git a/tests/unit/proxy/test__types.py b/tests/unit/proxy/test__types.py index c5a97fa4501..dd7bd86982e 100644 --- a/tests/unit/proxy/test__types.py +++ b/tests/unit/proxy/test__types.py @@ -61,7 +61,7 @@ def test_the_server_sets_a_marker_by_assignment_after_construction(marker): def test_a_virtual_key_is_hashed_out_of_the_auth_object(): - raw_key = "sk-1234567890abcdefghij" + raw_key = "sk-9876567890abcdefghij" auth = UserAPIKeyAuth(api_key=raw_key) @@ -70,7 +70,7 @@ def test_a_virtual_key_is_hashed_out_of_the_auth_object(): def test_a_bearer_prefixed_key_hashes_the_same_as_the_bare_key(): - raw_key = "sk-1234567890abcdefghij" + raw_key = "sk-9876567890abcdefghij" assert UserAPIKeyAuth(api_key=f"Bearer {raw_key}").token == UserAPIKeyAuth(api_key=raw_key).token diff --git a/tests/unit/proxy/test_caching_routes.py b/tests/unit/proxy/test_caching_routes.py index 707d4a3f2c9..6f80c281565 100644 --- a/tests/unit/proxy/test_caching_routes.py +++ b/tests/unit/proxy/test_caching_routes.py @@ -51,7 +51,7 @@ def mock_redis_failure(mocker): def test_cache_ping_success(mock_redis_success): """Test successful cache ping with regular response""" - response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 200 data = response.json() @@ -72,7 +72,7 @@ def test_cache_ping_with_complex_objects(mock_redis_success, mocker): mock_redis_success.cache.complex_attr = ComplexObject() mock_redis_success.cache.datetime_attr = mocker.MagicMock() - response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 200 # Verify response is JSON serializable @@ -93,7 +93,7 @@ def test_cache_ping_with_circular_reference(mock_redis_success): circular_dict["self"] = circular_dict mock_redis_success.cache.circular_ref = circular_dict - response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 200 # Verify response is still JSON serializable @@ -103,7 +103,7 @@ def test_cache_ping_with_circular_reference(mock_redis_success): def test_cache_ping_failure(mock_redis_failure): """Test cache ping failure with expected error fields""" - response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 503 data = response.json() @@ -125,7 +125,7 @@ def test_cache_ping_failure(mock_redis_failure): def test_cache_ping_failure_does_not_expose_traceback(mock_redis_failure): """CWE-209: Stack trace and exception text must not appear in the HTTP 503 response body.""" - response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 503 data = response.json() @@ -162,7 +162,7 @@ def test_cache_ping_no_cache_initialized(): try: response = client.get( - "/cache/ping", headers={"Authorization": "Bearer sk-1234"} + "/cache/ping", headers={"Authorization": "Bearer sk-9876"} ) assert response.status_code == 503 @@ -190,7 +190,7 @@ def test_cache_ping_no_cache_does_not_expose_internals(): try: response = client.get( - "/cache/ping", headers={"Authorization": "Bearer sk-1234"} + "/cache/ping", headers={"Authorization": "Bearer sk-9876"} ) assert response.status_code == 503 @@ -225,7 +225,7 @@ def test_cache_ping_health_check_includes_only_cache_attributes(mock_redis_succe # Add a field on the underlying `cache` object that SHOULD appear mock_redis_success.cache.redis_kwargs = {"host": "localhost", "port": 6379} - response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"}) assert ( response.status_code == 200 ), f"Unexpected status code: {response.status_code}" @@ -253,7 +253,7 @@ def test_cache_ping_with_redis_version_float(mock_redis_success): # Set redis_version as a float mock_redis_success.cache.redis_version = 7.2 - response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-1234"}) + response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"}) assert response.status_code == 200 data = response.json() @@ -325,7 +325,7 @@ def test_cache_redis_info_no_cache(): litellm.cache = None response = client.get( - "/cache/redis/info", headers={"Authorization": "Bearer sk-1234"} + "/cache/redis/info", headers={"Authorization": "Bearer sk-9876"} ) assert response.status_code == 503 diff --git a/tests/unit/proxy/test_component_allowlists.py b/tests/unit/proxy/test_component_allowlists.py index e42bc85e5a0..2b6e1424cc0 100644 --- a/tests/unit/proxy/test_component_allowlists.py +++ b/tests/unit/proxy/test_component_allowlists.py @@ -41,6 +41,8 @@ from starlette.routing import Mount, Route from starlette.testclient import TestClient from starlette.types import Lifespan +from tests._master_key import MASTER_KEY + # Importing ``litellm.proxy.proxy_server`` runs its module-level setup, which # reads ``DATABASE_URL`` (Prisma) and ``LITELLM_MASTER_KEY``. Tier-zero CI # runners don't set these. We pin throwaway values before the import so the @@ -50,7 +52,7 @@ from starlette.types import Lifespan # treat a phantom database as available instead of skipping). _THROWAWAY_ENV = { "DATABASE_URL": "sqlite:///:memory:", - "LITELLM_MASTER_KEY": "sk-test-component-allowlist", + "LITELLM_MASTER_KEY": MASTER_KEY, } _PRE_EXISTING_ENV = {key: os.environ.get(key) for key in _THROWAWAY_ENV} for _key, _value in _THROWAWAY_ENV.items(): diff --git a/tests/unit/proxy/test_litellm_pre_call_utils.py b/tests/unit/proxy/test_litellm_pre_call_utils.py index c97a5d1337f..db2aec10fdb 100644 --- a/tests/unit/proxy/test_litellm_pre_call_utils.py +++ b/tests/unit/proxy/test_litellm_pre_call_utils.py @@ -1968,7 +1968,7 @@ async def test_add_litellm_data_to_request_audio_transcription_multipart(): request_mock.query_params = {} request_mock.headers = { "Content-Type": "multipart/form-data", - "Authorization": "Bearer sk-1234", + "Authorization": "Bearer sk-9876", } request_mock.client = MagicMock() request_mock.client.host = "127.0.0.1" @@ -4803,7 +4803,7 @@ async def test_bearer_token_not_in_debug_logs(): "messages": [{"role": "user", "content": "hi"}], } - user_api_key_dict = UserAPIKeyAuth(api_key="sk-1234") + user_api_key_dict = UserAPIKeyAuth(api_key="sk-9876") # Capture all debug log output from the proxy logger log_capture = StringIO() diff --git a/tests/unit/proxy/test_model_deprecations_endpoint.py b/tests/unit/proxy/test_model_deprecations_endpoint.py index 6495cf408e1..66da6bea2c2 100644 --- a/tests/unit/proxy/test_model_deprecations_endpoint.py +++ b/tests/unit/proxy/test_model_deprecations_endpoint.py @@ -16,7 +16,7 @@ client = TestClient(app) @pytest.fixture def authenticated_client(monkeypatch): app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876" ) monkeypatch.setattr( litellm, diff --git a/tests/unit/proxy/test_proxy_logging_hook_detection.py b/tests/unit/proxy/test_proxy_logging_hook_detection.py index 9eb89b2f301..182ef833069 100644 --- a/tests/unit/proxy/test_proxy_logging_hook_detection.py +++ b/tests/unit/proxy/test_proxy_logging_hook_detection.py @@ -241,20 +241,20 @@ def _streaming_logging_obj(): def test_stream_requires_guardrail_translation_route_detection(): assert ( ProxyLogging._stream_requires_guardrail_translation( - UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/messages") + UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/messages") ) is True ) assert ( ProxyLogging._stream_requires_guardrail_translation( - UserAPIKeyAuth(api_key="sk-1234", request_route="/chat/completions") + UserAPIKeyAuth(api_key="sk-9876", request_route="/chat/completions") ) is False ) - assert ProxyLogging._stream_requires_guardrail_translation(UserAPIKeyAuth(api_key="sk-1234")) is False + assert ProxyLogging._stream_requires_guardrail_translation(UserAPIKeyAuth(api_key="sk-9876")) is False assert ( ProxyLogging._stream_requires_guardrail_translation( - UserAPIKeyAuth(api_key="sk-1234", request_route="/route/without/call/types") + UserAPIKeyAuth(api_key="sk-9876", request_route="/route/without/call/types") ) is False ) @@ -296,7 +296,7 @@ async def test_post_call_stream_guardrail_blocks_anthropic_messages_stream(monke async def _drain(): async for chunk in proxy_logging.async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/messages"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/messages"), request_data=request_data, ): delivered.append(chunk) @@ -337,7 +337,7 @@ async def test_post_call_stream_guardrail_keeps_own_iterator_on_chat_completions delivered_text = "" async for chunk in proxy_logging.async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/chat/completions"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/chat/completions"), request_data={"model": "gpt-4o-mini", "metadata": {}}, ): for choice in chunk.choices: @@ -364,7 +364,7 @@ async def test_post_call_stream_records_masked_text_for_deferred_logging(monkeyp delivered_text = "" async for chunk in proxy_logging.async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/chat/completions"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/chat/completions"), request_data={"model": "gpt-4o-mini", "metadata": {}, "litellm_logging_obj": logging_obj}, ): for choice in chunk.choices: @@ -390,7 +390,7 @@ async def test_post_call_stream_records_the_served_text_when_the_client_disconne stream = proxy_logging.async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/chat/completions"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/chat/completions"), request_data={"model": "gpt-4o-mini", "metadata": {}, "litellm_logging_obj": logging_obj}, ) first = await stream.__anext__() @@ -425,7 +425,7 @@ async def test_unified_guardrail_iterator_accepts_explicit_guardrail(): delivered = [] async for item in unified_guardrail.async_post_call_streaming_iterator_hook( - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/messages"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/messages"), response=fake_stream(), request_data=request_data, guardrail_to_apply=guardrail, @@ -478,7 +478,7 @@ async def test_post_call_stream_guardrail_reroutes_inherited_apply_guardrail(mon async def _drain(): async for chunk in proxy_logging.async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/messages"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/messages"), request_data=request_data, ): delivered.append(chunk) @@ -530,7 +530,7 @@ async def test_post_call_stream_masking_guardrail_keeps_own_iterator_on_anthropi delivered = [] async for chunk in proxy_logging.async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/messages"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/messages"), request_data={ "model": "claude-sonnet-5", "litellm_logging_obj": _streaming_logging_obj(), @@ -585,7 +585,7 @@ async def test_post_call_stream_presidio_output_masking_masks_anthropic_messages delivered = [] async for chunk in ProxyLogging(user_api_key_cache=DualCache()).async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/messages"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/messages"), request_data={ "model": "claude-sonnet-5", "litellm_logging_obj": _streaming_logging_obj(), @@ -663,7 +663,7 @@ async def test_execute_guardrail_hook_routes_apply_guardrail_implementers_to_uni callback=guardrail, hook_type=hook_type, data=data, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), call_type="completion", response=None, ) @@ -683,7 +683,7 @@ async def test_execute_guardrail_hook_keeps_native_hooks_when_opted_out(hook_typ callback=guardrail, hook_type=hook_type, data=data, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), call_type="completion", response=None, ) @@ -713,7 +713,7 @@ async def test_during_call_hook_keeps_native_moderation_hook_when_opted_out(monk await ProxyLogging(user_api_key_cache=DualCache()).during_call_hook( data={"messages": [{"role": "user", "content": "hi"}]}, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), call_type="completion", ) @@ -744,7 +744,7 @@ async def test_during_call_hook_runs_custom_logger_moderation_override(monkeypat with pytest.raises(HTTPException) as exc_info: await ProxyLogging(user_api_key_cache=DualCache()).during_call_hook( data={"messages": [{"role": "user", "content": "hi"}]}, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), call_type="acompletion", ) @@ -787,7 +787,7 @@ async def test_during_call_hook_runs_moderation_override_after_v1_pre_call_guard with pytest.raises(HTTPException) as exc_info: await ProxyLogging(user_api_key_cache=DualCache()).during_call_hook( data={"messages": [{"role": "user", "content": "hi"}]}, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), call_type="acompletion", ) @@ -803,7 +803,7 @@ async def test_during_call_hook_runs_moderation_override_inherited_from_parent(m with pytest.raises(HTTPException) as exc_info: await ProxyLogging(user_api_key_cache=DualCache()).during_call_hook( data={"messages": [{"role": "user", "content": "hi"}]}, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), call_type="acompletion", ) @@ -823,7 +823,7 @@ async def test_post_call_success_hook_keeps_native_hook_when_opted_out(monkeypat await ProxyLogging(user_api_key_cache=DualCache()).post_call_success_hook( data={"messages": [{"role": "user", "content": "hi"}]}, response=response, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), ) assert opted_out.native_hooks_ran == ["post_call"] @@ -869,7 +869,7 @@ async def test_deferred_stream_guardrails_run_native_hook_when_opted_out(monkeyp await ProxyBaseLLMRequestProcessing._run_deferred_stream_guardrails( captured_data={"messages": [{"role": "user", "content": "hi"}]}, - captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), captured_logging_obj=_streaming_logging_obj(), assembled_response=ModelResponse(choices=[Choices(message=Message(role="assistant", content="hello"))]), cache_hit=False, @@ -896,7 +896,7 @@ async def test_deferred_stream_guardrails_skip_pipeline_managed_native_hook(monk "messages": [{"role": "user", "content": "hi"}], "metadata": {"_guardrail_pipelines": [("response-governance", pipeline)]}, }, - captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/chat/completions"), + captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/chat/completions"), captured_logging_obj=_streaming_logging_obj(), assembled_response=ModelResponse(choices=[Choices(message=Message(role="assistant", content="hello"))]), cache_hit=False, @@ -933,7 +933,7 @@ async def test_deferred_stream_guardrails_run_native_hook_whose_pipeline_could_n "messages": [{"role": "user", "content": "hi"}], "metadata": {"_guardrail_pipelines": [("response-governance", pipeline)]}, }, - captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/chat/completions"), + captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/chat/completions"), captured_logging_obj=_streaming_logging_obj(), assembled_response=ModelResponse(choices=[Choices(message=Message(role="assistant", content="hello"))]), cache_hit=False, @@ -959,7 +959,7 @@ async def test_deferred_stream_guardrails_run_native_hook_on_route_without_trans "messages": [{"role": "user", "content": "hi"}], "metadata": {"_guardrail_pipelines": [("response-governance", pipeline)]}, }, - captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/custom/stream"), + captured_user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/custom/stream"), captured_logging_obj=_streaming_logging_obj(), assembled_response=ModelResponse(choices=[Choices(message=Message(role="assistant", content="hello"))]), cache_hit=False, @@ -1032,7 +1032,7 @@ async def test_post_call_stream_keeps_own_iterator_when_opted_out(monkeypatch): delivered = [] async for chunk in ProxyLogging(user_api_key_cache=DualCache()).async_post_call_streaming_iterator_hook( response=fake_stream(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/messages"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/messages"), request_data={"model": "claude-sonnet-5", "litellm_logging_obj": _streaming_logging_obj(), "metadata": {}}, ): delivered.append(chunk) @@ -1055,7 +1055,7 @@ async def test_parallel_post_call_guardrails_keep_native_hook_when_opted_out(mon await ProxyLogging(user_api_key_cache=DualCache()).post_call_success_hook( data={"messages": [{"role": "user", "content": "hi"}]}, response=response, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), ) assert opted_out.native_hooks_ran == ["post_call"] diff --git a/tests/unit/proxy/test_proxy_reject_logging.py b/tests/unit/proxy/test_proxy_reject_logging.py index 4e250ed3c52..6e8545a58b3 100644 --- a/tests/unit/proxy/test_proxy_reject_logging.py +++ b/tests/unit/proxy/test_proxy_reject_logging.py @@ -83,7 +83,7 @@ def router() -> Router: "litellm_params": { "model": "openai/fake", "api_base": "https://exampleopenaiendpoint-production.up.railway.app/", - "api_key": "sk-12345", + "api_key": "sk-98765", }, } ] @@ -115,7 +115,7 @@ def _register_proxy_test_logger(callback_logger: testLogger) -> None: "messages": [ { "role": "user", - "content": "Hello here is my OPENAI_API_KEY = sk-12345", + "content": "Hello here is my OPENAI_API_KEY = sk-98765", } ], }, @@ -174,8 +174,8 @@ async def test_chat_completion_request_with_redaction(route, body, router, monke response = await chat_completion( request=request, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-12345", - token="hashed_sk-12345", + api_key="sk-98765", + token="hashed_sk-98765", rpm_limit=0, request_route=route, ), @@ -185,8 +185,8 @@ async def test_chat_completion_request_with_redaction(route, body, router, monke response = await completion( request=request, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-12345", - token="hashed_sk-12345", + api_key="sk-98765", + token="hashed_sk-98765", rpm_limit=0, request_route=route, ), @@ -196,8 +196,8 @@ async def test_chat_completion_request_with_redaction(route, body, router, monke response = await embeddings( request=request, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-12345", - token="hashed_sk-12345", + api_key="sk-98765", + token="hashed_sk-98765", rpm_limit=0, request_route=route, ), diff --git a/tests/unit/proxy/test_proxy_server.py b/tests/unit/proxy/test_proxy_server.py index d6a2de157ff..9772988eac8 100644 --- a/tests/unit/proxy/test_proxy_server.py +++ b/tests/unit/proxy/test_proxy_server.py @@ -8,6 +8,8 @@ from unittest import mock from dotenv import load_dotenv +from tests._master_key import MASTER_KEY + import litellm.proxy import litellm.proxy.proxy_server @@ -233,7 +235,7 @@ async def test_proxy_shutdown_closes_admin_connector_when_drain_is_cancelled( # Your bearer token -token = "sk-1234" +token = MASTER_KEY headers = {"Authorization": f"Bearer {token}"} @@ -632,7 +634,7 @@ async def test_team_disable_guardrails(mock_acompletion, client_no_auth, monkeyp user_api_key_cache: Final = UserApiKeyCache() _team_id = "1234" - user_key = "sk-12345678" + user_key = "sk-98765678" valid_token = UserAPIKeyAuth( team_id=_team_id, @@ -651,7 +653,7 @@ async def test_team_disable_guardrails(mock_acompletion, client_no_auth, monkeyp user_api_key_cache.set_cache(key="team_id:{}".format(_team_id), value=team_obj) monkeypatch.setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "hello-world") request = Request(scope={"type": "http", "method": "POST", "path": "/chat/completions", "headers": []}) @@ -694,7 +696,7 @@ def test_custom_logger_failure_handler(mock_acompletion, client_no_auth, monkeyp proxy_logging_obj._init_litellm_callbacks(llm_router=None) monkeypatch.setattr(litellm.proxy.proxy_server, "user_api_key_cache", user_api_key_cache) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm.proxy.proxy_server, "prisma_client", "FAKE-VAR") setattr(litellm.proxy.proxy_server, "proxy_logging_obj", proxy_logging_obj) @@ -1307,8 +1309,6 @@ from litellm.proxy._types import ( from litellm.proxy.management_endpoints.internal_user_endpoints import new_user from litellm.proxy.management_endpoints.team_endpoints import team_member_add from tests.unit.proxy.management_endpoints.test_key_generate_prisma import prisma_client - - @pytest.fixture def mock_prisma_client(): client = MagicMock() @@ -1327,7 +1327,7 @@ def mock_prisma_client(): async def test_create_user_default_budget(prisma_client, user_role): # noqa: F811 # pytest fixture, not a redefinition setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm, "max_internal_user_budget", 10) setattr(litellm, "internal_user_budget_duration", "5m") await litellm.proxy.proxy_server.prisma_client.connect() @@ -1390,7 +1390,7 @@ async def test_create_team_member_add(prisma_client, new_member_method): # noqa from litellm.proxy.proxy_server import hash_token, user_api_key_cache setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm, "max_internal_user_budget", 10) setattr(litellm, "internal_user_budget_duration", "5m") await litellm.proxy.proxy_server.prisma_client.connect() @@ -1504,12 +1504,12 @@ async def test_create_team_member_add_team_admin_user_api_key_auth( user_api_key_cache: Final = UserApiKeyCache() setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm, "max_internal_user_budget", 10) setattr(litellm, "internal_user_budget_duration", "5m") user = f"ishaan {uuid.uuid4().hex}" _team_id = "litellm-test-client-id-new" - user_key = "sk-12345678" + user_key = "sk-98765678" valid_token = UserAPIKeyAuth( team_id=_team_id, @@ -1579,12 +1579,12 @@ async def test_create_team_member_add_team_admin( ) setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) setattr(litellm, "max_internal_user_budget", 10) setattr(litellm, "internal_user_budget_duration", "5m") user = f"ishaan {uuid.uuid4().hex}" _team_id = "litellm-test-client-id-new" - user_key = "sk-12345678" + user_key = "sk-98765678" team_admin = f"krrish {uuid.uuid4().hex}" valid_token = UserAPIKeyAuth( @@ -1705,7 +1705,7 @@ async def test_user_info_team_list(prisma_client): # noqa: F811 # pytest fixtu from litellm.proxy._types import LiteLLM_UserTable setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() from litellm.proxy.management_endpoints.internal_user_endpoints import user_info @@ -1729,7 +1729,7 @@ async def test_user_info_team_list(prisma_client): # noqa: F811 # pytest fixtu request=MagicMock(), user_id=None, user_api_key_dict=UserAPIKeyAuth( - api_key="sk-1234", user_id="default_user_id" + api_key=MASTER_KEY, user_id="default_user_id" ), ) except Exception: @@ -1753,7 +1753,7 @@ async def test_add_callback_via_key(prisma_client): # noqa: F811 # pytest fixt from litellm.proxy.proxy_server import chat_completion setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() litellm.set_verbose = True @@ -1850,7 +1850,7 @@ async def test_add_callback_via_key_litellm_pre_call_utils( from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request setattr(litellm.proxy.proxy_server, "prisma_client", mock_prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) proxy_config = getattr(litellm.proxy.proxy_server, "proxy_config") @@ -2009,7 +2009,7 @@ async def test_add_callback_via_key_litellm_pre_call_utils_gcs_bucket( from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request setattr(litellm.proxy.proxy_server, "prisma_client", mock_prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) proxy_config = getattr(litellm.proxy.proxy_server, "proxy_config") @@ -2145,7 +2145,7 @@ async def test_add_callback_via_key_litellm_pre_call_utils_langsmith( from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request setattr(litellm.proxy.proxy_server, "prisma_client", mock_prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) proxy_config = getattr(litellm.proxy.proxy_server, "proxy_config") @@ -2319,7 +2319,7 @@ async def test_proxy_model_group_alias_checks(prisma_client, hidden): # noqa: F from litellm.proxy.proxy_server import model_group_info, model_info_v1, model_list setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() proxy_config = getattr(litellm.proxy.proxy_server, "proxy_config") @@ -2400,7 +2400,7 @@ async def test_proxy_model_group_info_rerank(prisma_client): # noqa: F811 # py from litellm.proxy.proxy_server import model_group_info, model_info_v1, model_list setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) - setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") + setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) await litellm.proxy.proxy_server.prisma_client.connect() proxy_config = getattr(litellm.proxy.proxy_server, "proxy_config") @@ -2454,7 +2454,7 @@ async def test_proxy_model_group_info_rerank(prisma_client): # noqa: F811 # py # from litellm.proxy._types import TeamMemberAddRequest, Member, NewTeamRequest # setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) -# setattr(litellm.proxy.proxy_server, "master_key", "sk-1234") +# setattr(litellm.proxy.proxy_server, "master_key", MASTER_KEY) # try: # async def test(): @@ -2463,7 +2463,7 @@ async def test_proxy_model_group_info_rerank(prisma_client): # noqa: F811 # py # user_api_key_dict = UserAPIKeyAuth( # user_role=LitellmUserRoles.PROXY_ADMIN, -# api_key="sk-1234", +# api_key=MASTER_KEY, # user_id="1234", # ) diff --git a/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py b/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py index e2fbd5dcd98..afdca207e24 100644 --- a/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py +++ b/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py @@ -45,6 +45,9 @@ from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.proxy.hooks.parallel_request_limiter_v3 import RequestRateLimiterStash from litellm.proxy.proxy_server import app, initialize, openai_exception_handler from litellm.utils import _invalidate_model_cost_lowercase_map +from tests._master_key import MASTER_KEY + +PUBLICLY_KNOWN_KEY: Final = "sk-" + "1234" example_embedding_result = { "object": "list", @@ -1258,7 +1261,7 @@ def test_get_config_custom_callback_api_env_vars(monkeypatch): # Bypass auth dependency original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY ) client = TestClient(app) @@ -1307,7 +1310,7 @@ def test_get_config_callbacks_fall_back_to_process_env(mock_env_vars, monkeypatc original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY ) client = TestClient(app) @@ -1404,7 +1407,7 @@ def test_get_config_returns_email_settings(monkeypatch): original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY ) client = TestClient(app) @@ -1441,7 +1444,7 @@ def _get_email_alert_variables(monkeypatch, config_data): original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY ) client = TestClient(app) @@ -1566,7 +1569,7 @@ def test_get_config_returns_slack_webhook(monkeypatch): original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY ) client = TestClient(app) @@ -1616,7 +1619,7 @@ def test_get_config_cleared_slack_webhook_not_overridden_by_os_env(monkeypatch): original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY ) client = TestClient(app) @@ -1670,7 +1673,7 @@ async def test_aaaproxy_startup_master_key(mock_prisma, monkeypatch, tmp_path): app = FastAPI() # Test Case 1: Master key from config.yaml - test_master_key = "sk-12345" + test_master_key = MASTER_KEY test_config = {"general_settings": {"master_key": test_master_key}} # Create a temporary config file @@ -1689,7 +1692,7 @@ async def test_aaaproxy_startup_master_key(mock_prisma, monkeypatch, tmp_path): assert master_key == test_master_key # Test Case 2: Master key from environment variable - test_env_master_key = "sk-test-67890" + test_env_master_key = f"{MASTER_KEY}-environment" # Create empty config empty_config = {"general_settings": {}} @@ -1704,7 +1707,7 @@ async def test_aaaproxy_startup_master_key(mock_prisma, monkeypatch, tmp_path): assert master_key == test_env_master_key # Test Case 3: Master key with os.environ prefix - test_resolved_key = "sk-resolved-key" + test_resolved_key = f"{MASTER_KEY}-resolved" test_config_with_prefix = {"general_settings": {"master_key": "os.environ/CUSTOM_MASTER_KEY"}} # Create config with os.environ prefix @@ -1743,7 +1746,7 @@ def _boot_with_general_settings(monkeypatch, tmp_path, general_settings): @pytest.mark.asyncio @pytest.mark.parametrize( "general_settings", - [{"master_key": "sk-1234"}, {"master_key": ""}, {"master_key": None}, {}], + [{"master_key": PUBLICLY_KNOWN_KEY}, {"master_key": ""}, {"master_key": None}, {}], ids=["publicly-known", "empty", "yaml-null", "no-general-settings"], ) async def test_proxy_startup_refuses_an_unsafe_master_key_even_when_the_database_is_unreachable( @@ -1887,7 +1890,9 @@ class _DatabaseWithOneStoredCredential: @pytest.mark.asyncio -@pytest.mark.parametrize("encrypted_with, asks_to_migrate", [("sk-1234", True), ("sk-some-other-key", False)]) +@pytest.mark.parametrize( + "encrypted_with, asks_to_migrate", [(PUBLICLY_KNOWN_KEY, True), ("sk-some-other-key", False)] +) async def test_proxy_startup_asks_to_migrate_only_when_the_database_holds_values_under_the_unsafe_key( monkeypatch, tmp_path, encrypted_with, asks_to_migrate ): @@ -1902,7 +1907,7 @@ async def test_proxy_startup_asks_to_migrate_only_when_the_database_holds_values async def connected(): return database - _, announced = _boot_with_general_settings(monkeypatch, tmp_path, {"master_key": "sk-1234"}) + _, announced = _boot_with_general_settings(monkeypatch, tmp_path, {"master_key": PUBLICLY_KNOWN_KEY}) monkeypatch.setenv("DATABASE_URL", "postgresql://nobody:nothing@127.0.0.1:1/unreachable") monkeypatch.setattr("litellm.proxy.proxy_server._connect_to_count_stored_values", connected) @@ -1910,7 +1915,7 @@ async def test_proxy_startup_asks_to_migrate_only_when_the_database_holds_values async with proxy_startup_event(FastAPI()): pass - assert ("LITELLM_MIGRATE_FROM_MASTER_KEY=sk-1234" in announced[0]) == asks_to_migrate + assert (f"LITELLM_MIGRATE_FROM_MASTER_KEY={PUBLICLY_KNOWN_KEY}" in announced[0]) == asks_to_migrate assert ("holds 1 value(s) encrypted with this master key" in announced[0]) == asks_to_migrate @@ -1949,7 +1954,7 @@ async def test_proxy_startup_stops_when_the_requested_migration_fails(monkeypatc _boot_with_general_settings(monkeypatch, tmp_path, {"master_key": "sk-a-safe-master-key"}) monkeypatch.setattr("litellm.proxy.proxy_server.prisma_client", _PrismaClientWhoseDatabaseRejectsQueries()) - monkeypatch.setenv("LITELLM_MIGRATE_FROM_MASTER_KEY", "sk-1234") + monkeypatch.setenv("LITELLM_MIGRATE_FROM_MASTER_KEY", PUBLICLY_KNOWN_KEY) with ( caplog.at_level(logging.WARNING, logger="LiteLLM Proxy"), @@ -1970,7 +1975,9 @@ async def test_proxy_startup_names_the_config_file_that_set_the_unsafe_key(monke from litellm.proxy.auth.master_key_boot_check import UnsafeMasterKeyError from litellm.proxy.proxy_server import proxy_startup_event - config_path, announced = _boot_with_general_settings(monkeypatch, tmp_path, {"master_key": "sk-1234"}) + config_path, announced = _boot_with_general_settings( + monkeypatch, tmp_path, {"master_key": PUBLICLY_KNOWN_KEY} + ) with pytest.raises(UnsafeMasterKeyError): async with proxy_startup_event(FastAPI()): @@ -1987,7 +1994,7 @@ async def test_proxy_startup_boots_an_unsafe_master_key_under_the_override(monke from litellm.proxy.proxy_server import proxy_startup_event general_settings = { - "master_key": "sk-1234", + "master_key": PUBLICLY_KNOWN_KEY, **({"dangerously_permit_weak_or_unset_master_key": True} if override == "yaml" else {}), } _, announced = _boot_with_general_settings(monkeypatch, tmp_path, general_settings) @@ -1997,7 +2004,7 @@ async def test_proxy_startup_boots_an_unsafe_master_key_under_the_override(monke async with proxy_startup_event(FastAPI()): from litellm.proxy.proxy_server import master_key - assert master_key == "sk-1234" + assert master_key == PUBLICLY_KNOWN_KEY assert announced == [] @@ -2018,7 +2025,7 @@ async def test_proxy_shutdown_stops_the_view_setup_task(monkeypatch, tmp_path): fake_prisma = _ShutdownAwarePrisma() config_path = tmp_path / "config.yaml" with open(config_path, "w") as f: - yaml.dump({"general_settings": {"master_key": "sk-12345"}}, f) + yaml.dump({"general_settings": {"master_key": MASTER_KEY}}, f) monkeypatch.setenv("CONFIG_FILE_PATH", str(config_path)) monkeypatch.setattr(proxy_server_module, "prisma_client", fake_prisma) monkeypatch.setattr(proxy_server_module, "store_model_in_db", False) @@ -5514,9 +5521,9 @@ class TestPriceDataReloadIntegration: def test_config_file_parsing(self): """Test parsing of config file with reload settings""" - config_content = """ + config_content = f""" general_settings: - master_key: sk-1234 + master_key: {MASTER_KEY} model_cost_map_reload_interval: 21600 model_list: @@ -6085,7 +6092,7 @@ def test_model_info_v1_list_skips_fastapi_jsonable_encoder(monkeypatch): original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", models=[], team_models=[] + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, models=[], team_models=[] ) client = TestClient(app) try: @@ -6119,7 +6126,7 @@ def test_model_info_v1_cli_model_returns_single_deployment_as_json(monkeypatch): original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234", models=[], team_models=[] + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, models=[], team_models=[] ) client = TestClient(app) try: @@ -7200,7 +7207,7 @@ def test_get_config_normalizes_string_callbacks(monkeypatch): original_overrides = app.dependency_overrides.copy() app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY ) client = TestClient(app) @@ -8264,7 +8271,7 @@ async def test_update_general_settings_keeps_yaml_pass_through_endpoints_next_to "litellm.proxy.proxy_server.initialize_pass_through_endpoints", AsyncMock() ) # test-quality-ok: route registration needs the FastAPI app; auth is the observable here master_key: Final = patch( - "litellm.proxy.proxy_server.master_key", "sk-master" + "litellm.proxy.proxy_server.master_key", MASTER_KEY ) # test-quality-ok: a set master key is what makes a missing Authorization header a 401 with settings, yaml_endpoints, initialize, master_key: await ProxyConfig()._update_general_settings(db_general_settings={"pass_through_endpoints": [db_endpoint]}) @@ -8312,7 +8319,7 @@ async def test_update_general_settings_db_pass_through_endpoint_overrides_yaml_e settings: Final = patch("litellm.proxy.proxy_server.general_settings", {"pass_through_endpoints": [yaml_endpoint]}) # test-quality-ok: the method reads this module global; no injection seam yaml_endpoints: Final = patch("litellm.proxy.proxy_server.config_passthrough_endpoints", [yaml_endpoint]) # test-quality-ok: module global holding the YAML endpoints the fix merges in initialize: Final = patch("litellm.proxy.proxy_server.initialize_pass_through_endpoints", AsyncMock()) # test-quality-ok: route registration needs the FastAPI app; auth is the observable here - master_key: Final = patch("litellm.proxy.proxy_server.master_key", "sk-master") # test-quality-ok: a set master key is what makes a missing Authorization header a 401 + master_key: Final = patch("litellm.proxy.proxy_server.master_key", MASTER_KEY) # test-quality-ok: a set master key is what makes a missing Authorization header a 401 with settings, yaml_endpoints, initialize, master_key: await ProxyConfig()._update_general_settings(db_general_settings={"pass_through_endpoints": [db_endpoint]}) @@ -10029,7 +10036,7 @@ def _update_config_setup(monkeypatch): app.dependency_overrides[auth_dep] = lambda: UserAPIKeyAuth( user_id="test_admin", user_role=LitellmUserRoles.PROXY_ADMIN, - api_key="sk-1234", + api_key=MASTER_KEY, ) client = TestClient(app) @@ -12167,7 +12174,7 @@ async def test_failed_config_load_keeps_callbacks_the_stored_config_registered(m pc = ps.ProxyConfig() monkeypatch.setattr(ps, "proxy_config", pc) monkeypatch.setattr(ps, "llm_router", None) - monkeypatch.setattr(ps, "master_key", "sk-1234") + monkeypatch.setattr(ps, "master_key", MASTER_KEY) monkeypatch.setattr( pc, "get_config", AsyncMock(return_value={"litellm_settings": {"success_callback": ["helicone"]}}) ) diff --git a/tests/unit/proxy/test_proxy_types.py b/tests/unit/proxy/test_proxy_types.py index 5d5273be243..4d0689f4260 100644 --- a/tests/unit/proxy/test_proxy_types.py +++ b/tests/unit/proxy/test_proxy_types.py @@ -28,8 +28,8 @@ def test_audit_log_masking(): table_name="LiteLLM_VerificationToken", object_id="test", action="updated", - updated_values=json.dumps({"key": "sk-1234567890", "token": "1q2132r222"}), - before_value=json.dumps({"key": "sk-1234567890", "token": "1q2132r222"}), + updated_values=json.dumps({"key": "sk-1987657890", "token": "1q2132r222"}), + before_value=json.dumps({"key": "sk-1987657890", "token": "1q2132r222"}), ) print(audit_log.updated_values) @@ -147,8 +147,8 @@ def test_update_key_request_requires_key_or_key_alias(): with pytest.raises(pydantic.ValidationError, match="either key or key_alias must be provided"): UpdateKeyRequest(max_budget=10.0) - by_key = UpdateKeyRequest(key="sk-1234") - assert by_key.key == "sk-1234" + by_key = UpdateKeyRequest(key="sk-9876") + assert by_key.key == "sk-9876" assert by_key.key_alias is None by_alias = UpdateKeyRequest(key_alias="my-alias") @@ -211,12 +211,12 @@ def test_a_temp_budget_needs_both_halves_or_neither(): from litellm.proxy._types import UpdateKeyRequest with pytest.raises(ValidationError, match="temp_budget_increase and temp_budget_expiry must be set together"): - UpdateKeyRequest(key="sk-1234", temp_budget_increase=10) + UpdateKeyRequest(key="sk-9876", temp_budget_increase=10) with pytest.raises(ValidationError, match="temp_budget_increase and temp_budget_expiry must be set together"): - UpdateKeyRequest(key="sk-1234", temp_budget_expiry="2026-01-01") + UpdateKeyRequest(key="sk-9876", temp_budget_expiry="2026-01-01") - both = UpdateKeyRequest(key="sk-1234", temp_budget_increase=10, temp_budget_expiry="2026-01-01") + both = UpdateKeyRequest(key="sk-9876", temp_budget_increase=10, temp_budget_expiry="2026-01-01") assert both.temp_budget_increase == 10 @@ -273,7 +273,7 @@ def test_an_llm_backed_injection_check_needs_the_call_it_would_make(): def test_a_server_only_marker_is_not_taken_from_the_caller(field, forged, default): from litellm.proxy._types import UserAPIKeyAuth - auth = UserAPIKeyAuth(api_key="sk-1234", **{field: forged}) + auth = UserAPIKeyAuth(api_key="sk-9876", **{field: forged}) assert getattr(auth, field) == default diff --git a/tests/unit/proxy/test_proxy_utils.py b/tests/unit/proxy/test_proxy_utils.py index 44ab2155734..f52a5bd431a 100644 --- a/tests/unit/proxy/test_proxy_utils.py +++ b/tests/unit/proxy/test_proxy_utils.py @@ -1577,14 +1577,14 @@ def test_get_model_group_info(): "model_name": "openai/tts-1", "litellm_params": { "model": "openai/tts-1", - "api_key": "sk-1234", + "api_key": "sk-9876", }, }, { "model_name": "openai/gpt-3.5-turbo", "litellm_params": { "model": "openai/gpt-3.5-turbo", - "api_key": "sk-1234", + "api_key": "sk-9876", }, }, ] diff --git a/tests/unit/proxy/test_proxy_utils_model_creation_and_error_logging.py b/tests/unit/proxy/test_proxy_utils_model_creation_and_error_logging.py index 0a095183b6e..34260908a5c 100644 --- a/tests/unit/proxy/test_proxy_utils_model_creation_and_error_logging.py +++ b/tests/unit/proxy/test_proxy_utils_model_creation_and_error_logging.py @@ -149,7 +149,7 @@ async def test_proxy_only_error_log_keeps_litellm_metadata_in_litellm_params(): "input": "blocked prompt", "litellm_metadata": {"standard_logging_guardrail_information": guardrail_info}, }, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/responses"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/responses"), route="/v1/responses", original_exception=HTTPException(status_code=400, detail="blocked"), ) @@ -203,14 +203,14 @@ def test_get_model_group_info_order(): "model_name": "openai/tts-1", "litellm_params": { "model": "openai/tts-1", - "api_key": "sk-1234", + "api_key": "sk-9876", }, }, { "model_name": "openai/gpt-3.5-turbo", "litellm_params": { "model": "openai/gpt-3.5-turbo", - "api_key": "sk-1234", + "api_key": "sk-9876", }, }, ] @@ -2090,7 +2090,7 @@ async def test_proxy_only_error_expected_4xx_skips_traceback_for_both_handlers(m "model": "does-not-exist", "messages": [{"role": "user", "content": "hi"}], }, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/chat/completions"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/chat/completions"), route="/v1/chat/completions", original_exception=exc, ) @@ -2141,7 +2141,7 @@ async def test_proxy_only_error_5xx_keeps_traceback_and_runs_sync_callbacks(monk "model": "gpt-4o", "messages": [{"role": "user", "content": "hi"}], }, - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234", request_route="/v1/chat/completions"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876", request_route="/v1/chat/completions"), route="/v1/chat/completions", original_exception=exc, ) diff --git a/tests/unit/proxy/test_response_model_sanitization.py b/tests/unit/proxy/test_response_model_sanitization.py index c20b1208e8f..ba66d27609b 100644 --- a/tests/unit/proxy/test_response_model_sanitization.py +++ b/tests/unit/proxy/test_response_model_sanitization.py @@ -9,6 +9,7 @@ from fastapi.testclient import TestClient import litellm +from tests._master_key import MASTER_KEY pytestmark = pytest.mark.flaky(condition=False) @@ -141,7 +142,7 @@ def test_proxy_chat_completion_does_not_return_provider_prefixed_model( client = _initialize_proxy_with_config( config={ - "general_settings": {"master_key": "sk-1234"}, + "general_settings": {"master_key": MASTER_KEY}, "model_list": [ { "model_name": client_model, @@ -180,7 +181,7 @@ def test_proxy_chat_completion_does_not_return_provider_prefixed_model( resp = client.post( "/v1/chat/completions", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": f"Bearer {MASTER_KEY}"}, json={"model": client_model, "messages": [{"role": "user", "content": "hi"}]}, ) @@ -240,7 +241,7 @@ async def test_proxy_streaming_chunks_do_not_return_provider_prefixed_model( MagicMock(return_value=True), ) - user_api_key_dict = UserAPIKeyAuth(api_key="sk-1234") + user_api_key_dict = UserAPIKeyAuth(api_key=MASTER_KEY) gen = proxy_server.async_data_generator( response=MagicMock(), @@ -313,7 +314,7 @@ async def test_proxy_streaming_chunks_use_client_requested_model_before_alias_ma MagicMock(return_value=True), ) - user_api_key_dict = UserAPIKeyAuth(api_key="sk-1234") + user_api_key_dict = UserAPIKeyAuth(api_key=MASTER_KEY) gen = proxy_server.async_data_generator( response=MagicMock(), @@ -385,7 +386,7 @@ async def test_proxy_streaming_azure_model_router_preserves_actual_model(monkeyp MagicMock(return_value=True), ) - user_api_key_dict = UserAPIKeyAuth(api_key="sk-1234") + user_api_key_dict = UserAPIKeyAuth(api_key=MASTER_KEY) gen = proxy_server.async_data_generator( response=MagicMock(), @@ -458,7 +459,7 @@ async def test_proxy_streaming_fastest_response_preserves_winning_model(monkeypa MagicMock(return_value=True), ) - user_api_key_dict = UserAPIKeyAuth(api_key="sk-1234") + user_api_key_dict = UserAPIKeyAuth(api_key=MASTER_KEY) gen = proxy_server.async_data_generator( response=MagicMock(), diff --git a/tests/unit/proxy/test_update_llm_router_resilience.py b/tests/unit/proxy/test_update_llm_router_resilience.py index aaa9d144d4e..fde1e49e38a 100644 --- a/tests/unit/proxy/test_update_llm_router_resilience.py +++ b/tests/unit/proxy/test_update_llm_router_resilience.py @@ -12,6 +12,7 @@ import pytest from unittest.mock import AsyncMock, MagicMock, patch from litellm.proxy.proxy_server import ProxyConfig +from tests._master_key import MASTER_KEY def _make_db_model(model_name: str, model_id: str): @@ -311,7 +312,7 @@ class TestDeleteDeploymentKeepsConfigModelsOnEmptyConfigRead: @pytest.mark.asyncio async def test_delete_deployment_keeps_config_models_when_config_read_has_no_model_list(self, tmp_path): config_file_path = str(tmp_path / "config.yaml") - (tmp_path / "config.yaml").write_text("general_settings:\n master_key: sk-1234\n") + (tmp_path / "config.yaml").write_text(f"general_settings:\n master_key: {MASTER_KEY}\n") router = self._router( [ diff --git a/tests/unit/proxy/ui_crud_endpoints/test_latest_release_endpoints.py b/tests/unit/proxy/ui_crud_endpoints/test_latest_release_endpoints.py index c966b8b7135..ae0ac32c62d 100644 --- a/tests/unit/proxy/ui_crud_endpoints/test_latest_release_endpoints.py +++ b/tests/unit/proxy/ui_crud_endpoints/test_latest_release_endpoints.py @@ -24,6 +24,7 @@ from litellm.proxy.ui_crud_endpoints.latest_release_endpoints import ( count_release_bullets, get_latest_release_info, ) +from tests._master_key import MASTER_KEY SAMPLE_BODY: Final = """## What's Changed * feat(proxy): add upgrade banner by @kerry in https://github.com/BerriAI/litellm/pull/1 @@ -255,6 +256,6 @@ class TestLatestReleaseInfoEndpoint: assert len(client.calls) == 1 def test_rejects_unauthenticated_requests(self, monkeypatch): - monkeypatch.setattr("litellm.proxy.proxy_server.master_key", "sk-1234") + monkeypatch.setattr("litellm.proxy.proxy_server.master_key", MASTER_KEY) response = TestClient(app).get("/get/latest_release_info") assert response.status_code in (401, 403) diff --git a/tests/unit/proxy/ui_crud_endpoints/test_user_banner_endpoints.py b/tests/unit/proxy/ui_crud_endpoints/test_user_banner_endpoints.py index 5d4875073fd..c014ffd04c6 100644 --- a/tests/unit/proxy/ui_crud_endpoints/test_user_banner_endpoints.py +++ b/tests/unit/proxy/ui_crud_endpoints/test_user_banner_endpoints.py @@ -8,6 +8,7 @@ from fastapi.testclient import TestClient from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.proxy.proxy_server import app +from tests._master_key import MASTER_KEY client = TestClient(app) @@ -60,7 +61,7 @@ def _mock_prisma(monkeypatch, record=None): class TestGetUserBanner: def test_requires_auth(self, monkeypatch): _mock_prisma(monkeypatch) - monkeypatch.setattr("litellm.proxy.proxy_server.master_key", "sk-1234") + monkeypatch.setattr("litellm.proxy.proxy_server.master_key", MASTER_KEY) response = client.get("/get/user_banner") assert response.status_code in (401, 403) diff --git a/tests/unit/router_strategy/adaptive_router/test_state_endpoint.py b/tests/unit/router_strategy/adaptive_router/test_state_endpoint.py index 5662870a5cb..dbb277d0f0e 100644 --- a/tests/unit/router_strategy/adaptive_router/test_state_endpoint.py +++ b/tests/unit/router_strategy/adaptive_router/test_state_endpoint.py @@ -109,7 +109,7 @@ async def test_endpoint_returns_404_when_no_adaptive_router(monkeypatch): fake_router.adaptive_routers = {} monkeypatch.setattr(proxy_server, "llm_router", fake_router) - admin = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + admin = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) with pytest.raises(HTTPException) as exc: await proxy_server.get_adaptive_router_state(user_api_key_dict=admin) assert exc.value.status_code == 404 @@ -121,7 +121,7 @@ async def test_endpoint_returns_404_when_llm_router_is_none(monkeypatch): monkeypatch.setattr(proxy_server, "llm_router", None) - admin = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + admin = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) with pytest.raises(HTTPException) as exc: await proxy_server.get_adaptive_router_state(user_api_key_dict=admin) assert exc.value.status_code == 404 @@ -152,7 +152,7 @@ async def test_endpoint_returns_snapshot_list_for_admin(monkeypatch): fake_router.adaptive_routers = {"r1": _entry("r1")} monkeypatch.setattr(proxy_server, "llm_router", fake_router) - admin = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + admin = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) result = await proxy_server.get_adaptive_router_state(user_api_key_dict=admin) assert list(result.keys()) == ["routers"] assert len(result["routers"]) == 1 @@ -174,7 +174,7 @@ async def test_endpoint_returns_one_snapshot_per_router(monkeypatch): } monkeypatch.setattr(proxy_server, "llm_router", fake_router) - admin = UserAPIKeyAuth(api_key="sk-1234", user_role=LitellmUserRoles.PROXY_ADMIN) + admin = UserAPIKeyAuth(api_key="sk-9876", user_role=LitellmUserRoles.PROXY_ADMIN) result = await proxy_server.get_adaptive_router_state(user_api_key_dict=admin) names = sorted(s["router_name"] for s in result["routers"]) assert names == ["r1", "r2"] diff --git a/tests/unit/router_utils/test_cooldown_cache.py b/tests/unit/router_utils/test_cooldown_cache.py index 06dd294fc11..7a8b9c5d15a 100644 --- a/tests/unit/router_utils/test_cooldown_cache.py +++ b/tests/unit/router_utils/test_cooldown_cache.py @@ -97,7 +97,7 @@ class TestCooldownCacheExceptionMasking: def test_exception_with_api_keys_masked(self, cooldown_cache): """Test that API keys in exceptions are properly masked""" exception_with_key = ( - "Authentication failed with api_key=sk-1234567890abcdefghijklmnopqrstuvwxyz " + "Authentication failed with api_key=sk-9876567890abcdefghijklmnopqrstuvwxyz " "and token=bearer_token_123456789 for model gpt-4" ) @@ -115,7 +115,7 @@ class TestCooldownCacheExceptionMasking: masked_exception = cooldown_data["exception_received"] # Should mask the sensitive content while preserving structure - assert masked_exception.startswith("Authentication failed with api_key=sk-12345678") + assert masked_exception.startswith("Authentication failed with api_key=sk-98765678") assert "*" in masked_exception assert len(masked_exception) == len(exception_with_key) diff --git a/tests/unit/test_lens_dev.py b/tests/unit/test_lens_dev.py index bc73695f898..1f7df52e6a6 100644 --- a/tests/unit/test_lens_dev.py +++ b/tests/unit/test_lens_dev.py @@ -88,7 +88,7 @@ def test_default_master_key_is_random_and_stable(tmp_path): second = _run(tmp_path, 'load_master_key; echo "$master_key"') assert first.returncode == 0, first.stderr key = first.stdout.strip() - assert key.startswith("sk-") and len(key) == 51 and key != "sk-1234" + assert key.startswith("sk-") and len(key) == 51 assert second.stdout.strip() == key assert oct((tmp_path / "state" / "master_key").stat().st_mode & 0o777) == "0o600" @@ -119,9 +119,10 @@ def test_proxy_env_drops_inherited_redis_and_base_urls(tmp_path): assert "LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY" not in names -def test_proxy_env_permits_the_weak_key_only_when_chosen(tmp_path): - proc = _run(tmp_path, 'master_key=sk-1234; proxy_env ""; env') - assert "LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY=true" in proc.stdout +def test_proxy_env_does_not_enable_weak_key_override(tmp_path): + proc = _run(tmp_path, 'master_key="$(printf "sk-%s" "1234")"; proxy_env ""; env') + assert proc.returncode == 0, proc.stderr + assert "LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY" not in proc.stdout def test_source_development_overrides_an_inherited_release_with_its_own_commit(tmp_path: Path) -> None: diff --git a/tests/unit/test_logging.py b/tests/unit/test_logging.py index 5cdecc31575..da67cf60756 100644 --- a/tests/unit/test_logging.py +++ b/tests/unit/test_logging.py @@ -812,7 +812,7 @@ def test_secret_filter_keeps_truncated_traceback(monkeypatch): traceback instead of reformatting the full one from exc_info.""" monkeypatch.setenv("MAX_STRING_LENGTH_STDOUT_LOG", "500") try: - raise ValueError("sk-1234567890abcdefghij payload " + _OVERSIZED_TEXT) + raise ValueError("sk-9876567890abcdefghij payload " + _OVERSIZED_TEXT) except ValueError: exc_info = sys.exc_info() record = _make_record(logging.ERROR, "Exception occured", exc_info=exc_info) @@ -822,7 +822,7 @@ def test_secret_filter_keeps_truncated_traceback(monkeypatch): assert record.exc_text is not None assert len(record.exc_text) <= 500 - assert "sk-1234567890abcdefghij" not in record.exc_text + assert "sk-9876567890abcdefghij" not in record.exc_text @pytest.mark.parametrize("native", (False, True), ids=("python", "rust")) @@ -1093,11 +1093,11 @@ def test_caller_supplied_stamp_never_skips_the_scrub(monkeypatch): monkeypatch.setenv("LITELLM_RUST", "0") monkeypatch.setattr(secret_redaction, "_SECRET_RE", counting) monkeypatch.setattr("litellm._logging._ENABLE_SECRET_REDACTION", True) - record = _make_record(logging.DEBUG, "api_key=sk-1234567890abcdefghij") + record = _make_record(logging.DEBUG, "api_key=sk-9876567890abcdefghij") record.litellm_redacted = True assert SecretRedactionFilter().filter(record) is True - assert "sk-1234567890abcdefghij" not in record.getMessage() + assert "sk-9876567890abcdefghij" not in record.getMessage() assert counting.calls == 1 assert SecretRedactionFilter().filter(record) is True @@ -1107,12 +1107,12 @@ def test_caller_supplied_stamp_never_skips_the_scrub(monkeypatch): def test_stack_info_is_scrubbed_before_the_plain_formatter(monkeypatch): monkeypatch.setattr("litellm._logging._ENABLE_SECRET_REDACTION", True) record = _make_record(logging.INFO, "call failed") - record.stack_info = "Stack (most recent call last):\n api_key=sk-1234567890abcdefghij" + record.stack_info = "Stack (most recent call last):\n api_key=sk-9876567890abcdefghij" assert SecretRedactionFilter().filter(record) is True rendered = CorrelationPlainFormatter(_PLAIN_LOG_FORMAT).format(record) - assert "sk-1234567890abcdefghij" not in rendered + assert "sk-9876567890abcdefghij" not in rendered assert "Stack (most recent call last):" in rendered @@ -1182,9 +1182,9 @@ def test_secret_free_extra_keeps_its_original_object(monkeypatch, extra): @pytest.mark.parametrize( "extra,scrubbed", ( - (("gpt-4o", "sk-1234567890abcdefghij"), ("gpt-4o", "REDACTED")), - ({"gpt-4o", "sk-1234567890abcdefghij"}, ["REDACTED", "gpt-4o"]), - ({"model": "gpt-4o", "key": "sk-1234567890abcdefghij"}, {"model": "gpt-4o", "key": "REDACTED"}), + (("gpt-4o", "sk-9876567890abcdefghij"), ("gpt-4o", "REDACTED")), + ({"gpt-4o", "sk-9876567890abcdefghij"}, ["REDACTED", "gpt-4o"]), + ({"model": "gpt-4o", "key": "sk-9876567890abcdefghij"}, {"model": "gpt-4o", "key": "REDACTED"}), ), ids=("tuple", "set", "dict"), ) @@ -1198,7 +1198,7 @@ def test_extra_that_carried_a_secret_comes_back_scrubbed(monkeypatch, extra, scr assert record.payload == scrubbed assert type(record.payload) is type(scrubbed) - assert "sk-1234567890abcdefghij" not in rendered + assert "sk-9876567890abcdefghij" not in rendered assert "REDACTED" in rendered @@ -1231,11 +1231,11 @@ def test_extra_whose_equality_raises_still_comes_back_scrubbed(monkeypatch, extr @pytest.mark.parametrize( "extra", ( - {1: "sk-1234567890abcdefghij"}, - {"model": {1: "sk-1234567890abcdefghij"}}, - _nest("sk-1234567890abcdefghij", 101), - _RequestExtra(model="gpt-4o", attempt=2, api_key="sk-1234567890abcdefghij"), - {"gpt-4o", "sk-1234567890abcdefghij", 1}, + {1: "sk-9876567890abcdefghij"}, + {"model": {1: "sk-9876567890abcdefghij"}}, + _nest("sk-9876567890abcdefghij", 101), + _RequestExtra(model="gpt-4o", attempt=2, api_key="sk-9876567890abcdefghij"), + {"gpt-4o", "sk-9876567890abcdefghij", 1}, ), ids=("int_key", "nested_int_key", "deeper_than_safe_dumps", "dataclass_hidden_field", "unsortable_set"), ) @@ -1250,8 +1250,8 @@ def test_extra_the_filter_cannot_fully_inspect_never_keeps_its_secret(monkeypatc rendered = JsonFormatter().format(record) assert record.payload is not extra - assert "sk-1234567890abcdefghij" not in str(record.payload) - assert "sk-1234567890abcdefghij" not in rendered + assert "sk-9876567890abcdefghij" not in str(record.payload) + assert "sk-9876567890abcdefghij" not in rendered def test_secret_free_set_comes_back_as_its_json_shape(monkeypatch): @@ -1269,10 +1269,10 @@ def test_unscrubbed_record_is_still_redacted_by_the_formatter(monkeypatch): """Records that never met SecretRedactionFilter (uvicorn's, in JSON mode) keep their formatter-side redaction.""" monkeypatch.setattr("litellm._logging._ENABLE_SECRET_REDACTION", True) - record = _make_record(logging.INFO, "key sk-1234567890abcdefghij") + record = _make_record(logging.INFO, "key sk-9876567890abcdefghij") - assert "sk-1234567890abcdefghij" not in JsonFormatter().format(record) - assert "sk-1234567890abcdefghij" not in CorrelationPlainFormatter(_PLAIN_LOG_FORMAT).format(record) + assert "sk-9876567890abcdefghij" not in JsonFormatter().format(record) + assert "sk-9876567890abcdefghij" not in CorrelationPlainFormatter(_PLAIN_LOG_FORMAT).format(record) def test_set_session_id_bounds_length(): diff --git a/tests/unit/test_redact_string_in_error_paths.py b/tests/unit/test_redact_string_in_error_paths.py index a5128a87b0d..74da68208cb 100644 --- a/tests/unit/test_redact_string_in_error_paths.py +++ b/tests/unit/test_redact_string_in_error_paths.py @@ -20,9 +20,9 @@ from litellm._logging import _ENABLE_SECRET_REDACTION, _redact_string class TestRedactStringFunction: def test_redacts_bearer_token(self): - text = "Authorization: Bearer sk-1234567890abcdefghij" + text = "Authorization: Bearer sk-9876567890abcdefghij" result = _redact_string(text) - assert "sk-1234567890abcdefghij" not in result + assert "sk-9876567890abcdefghij" not in result assert "REDACTED" in result def test_redacts_api_key_in_url(self): @@ -43,9 +43,9 @@ class TestRedactStringFunction: not _ENABLE_SECRET_REDACTION, reason="redaction disabled via env var" ) def test_redaction_enabled_by_default(self): - text = "Bearer sk-1234567890abcdefghij" + text = "Bearer sk-9876567890abcdefghij" result = _redact_string(text) - assert "sk-1234567890abcdefghij" not in result + assert "sk-9876567890abcdefghij" not in result class TestOpenAIRealtimeRedaction: @@ -78,7 +78,7 @@ class TestOpenAIRealtimeRedaction: handler = OpenAIRealtime() secret_error = RuntimeError( - "Connection failed for api_key=sk-1234567890abcdefghij" + "Connection failed for api_key=sk-9876567890abcdefghij" ) kwargs = self._call_kwargs() @@ -89,7 +89,7 @@ class TestOpenAIRealtimeRedaction: mock_ws.close.assert_called_once() assert mock_ws.close.call_args[1]["code"] == 1011 - assert "sk-1234567890abcdefghij" not in mock_ws.close.call_args[1]["reason"] + assert "sk-9876567890abcdefghij" not in mock_ws.close.call_args[1]["reason"] class TestBedrockRealtimeRedaction: @@ -121,14 +121,14 @@ class TestProxyStreamingDataGeneratorRedaction: def test_redact_traceback_format_exc(self): try: raise RuntimeError( - "Failed connecting to api_key=sk-1234567890abcdefghij at https://api.example.com" + "Failed connecting to api_key=sk-9876567890abcdefghij at https://api.example.com" ) except RuntimeError: raw_tb = traceback.format_exc() redacted_tb = _redact_string(raw_tb) - assert "sk-1234567890abcdefghij" not in redacted_tb + assert "sk-9876567890abcdefghij" not in redacted_tb assert "Traceback" in redacted_tb assert "RuntimeError" in redacted_tb diff --git a/tests/unit/test_router/test_router.py b/tests/unit/test_router/test_router.py index 114d7415840..290b4e62852 100644 --- a/tests/unit/test_router/test_router.py +++ b/tests/unit/test_router/test_router.py @@ -1595,7 +1595,7 @@ def test_arouter_responses_api_bridge(): "litellm_params": { "model": "azure/responses/o_series/webinterface-o3-pro", "api_base": "https://webhook.site/fba79dae-220a-4bb7-9a3a-8caa49604e55", - "api_key": "sk-1234567890", + "api_key": "sk-9876567890", "api_version": "preview", "stream": True, }, diff --git a/tests/unit/test_router_retry_policy_update.py b/tests/unit/test_router_retry_policy_update.py index b8c4e5fe084..48b5194a66e 100644 --- a/tests/unit/test_router_retry_policy_update.py +++ b/tests/unit/test_router_retry_policy_update.py @@ -439,7 +439,7 @@ async def test_config_update_persists_and_reads_back_retry_policy(monkeypatch): await proxy_server.update_config( config_info=ConfigYAML(router_settings=posted), request=request, - user_api_key_dict=UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876"), ) persisted = fake_table.rows["router_settings"].param_value["retry_policy"] @@ -455,7 +455,7 @@ async def test_config_update_persists_and_reads_back_retry_policy(monkeypatch): read_back = ( await proxy_server.get_config( user_api_key_dict=UserAPIKeyAuth( - user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-1234" + user_role=LitellmUserRoles.PROXY_ADMIN, api_key="sk-9876" ) ) )["router_settings"]["retry_policy"] diff --git a/tests/unit/test_seed_tracing_fixtures.py b/tests/unit/test_seed_tracing_fixtures.py index f7f4275eec4..626cb3543a9 100644 --- a/tests/unit/test_seed_tracing_fixtures.py +++ b/tests/unit/test_seed_tracing_fixtures.py @@ -15,6 +15,7 @@ from pydantic import InstanceOf, TypeAdapter from litellm.rust_bridge.trace.generated.responses import TraceSQLResponse from litellm.rust_bridge.trace.storage import Tenant, span_rows from litellm.tracing.types import SpendLogRecord +from tests._master_key import MASTER_KEY from scripts.seed_tracing_fixtures import ( JSON, TRACE_FIXTURES, @@ -217,7 +218,7 @@ async def test_first_copy_stamps_the_authenticated_tenant_and_writes_both_stores ) -> None: from litellm.rust_bridge.trace.storage import ClickHouseStorage - monkeypatch.setenv("LITELLM_MASTER_KEY", "sk-local") + monkeypatch.setenv("LITELLM_MASTER_KEY", MASTER_KEY) fixtures: Final = spend_fixtures() pattern: Final = response_pattern(tuple(chain.from_iterable(rows for _, rows in fixtures))) replays: Final = fixture_replays(TRACE_FIXTURES, 1_800_000_000_000, "first", pattern) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 47f893d0697..8bd12f7581c 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -2219,7 +2219,7 @@ def test_block_key_hashing_logic(): # Test cases: (input_key, should_be_hashed, expected_output) test_cases = [ - ("sk-1234567890abcdef", True, hash_token("sk-1234567890abcdef")), + ("sk-9876567890abcdef", True, hash_token("sk-9876567890abcdef")), ("sk-test-key", True, hash_token("sk-test-key")), ("abc123", False, "abc123"), # Should not be hashed ("hashed_key_123", False, "hashed_key_123"), # Should not be hashed diff --git a/tests/unit/test_video_generation.py b/tests/unit/test_video_generation.py index a1e5a335fd5..40fb6be67fe 100644 --- a/tests/unit/test_video_generation.py +++ b/tests/unit/test_video_generation.py @@ -1601,7 +1601,7 @@ class TestVideoEndpointsProxyLitellmParams: # Make request to video_status endpoint response = client_with_vertex_config.get( f"/v1/videos/{encoded_video_id}", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify the endpoint was called @@ -1670,7 +1670,7 @@ class TestVideoEndpointsProxyLitellmParams: # Make request to video_content endpoint response = client_with_vertex_config.get( f"/v1/videos/{encoded_video_id}/content", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify the endpoint was called @@ -1739,7 +1739,7 @@ class TestVideoEndpointsProxyLitellmParams: # Make request to video_content endpoint response = client_with_vertex_config.get( f"/v1/videos/{encoded_video_id}/content", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) # Verify the endpoint was called @@ -2268,7 +2268,7 @@ def test_video_create_character_target_model_names_returns_encoded_id( ): response = video_proxy_test_client.post( "/v1/videos/characters", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, files={"video": ("character.mp4", b"fake-video", "video/mp4")}, data={ "name": "hero", @@ -2321,7 +2321,7 @@ def test_video_get_character_accepts_encoded_character_id(video_proxy_test_clien ): response = video_proxy_test_client.get( f"/v1/videos/characters/{encoded_character_id}", - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, ) assert response.status_code == 200, response.text @@ -2366,7 +2366,7 @@ def test_edit_and_extension_support_custom_provider_from_extra_body( ): response = video_proxy_test_client.post( endpoint, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, json=payload, ) @@ -2432,7 +2432,7 @@ async def test_edit_and_extension_read_cached_body_after_auth_consumes_stream( await handler( request=request, fastapi_response=Response(), - user_api_key_dict=UserAPIKeyAuth(api_key="sk-1234"), + user_api_key_dict=UserAPIKeyAuth(api_key="sk-9876"), ) message = str(exc_info.value) @@ -2478,7 +2478,7 @@ def test_edit_and_extension_route_with_encoded_video_ids( ): response = video_proxy_test_client.post( endpoint, - headers={"Authorization": "Bearer sk-1234"}, + headers={"Authorization": "Bearer sk-9876"}, json=payload, ) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_speech.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_speech.test.tsx index 17f5d0f28a4..b7bf257b467 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_speech.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_speech.test.tsx @@ -41,7 +41,7 @@ describe("audio_speech", () => { }); it("should make a request to the audio speech API with basic parameters", async () => { - await makeOpenAIAudioSpeechRequest("Hello, world!", "alloy", mockUpdateUI, "tts-1", "sk-1234567890", []); + await makeOpenAIAudioSpeechRequest("Hello, world!", "alloy", mockUpdateUI, "tts-1", "sk-9876543210", []); expect(mockCreate).toHaveBeenCalledWith( { @@ -63,7 +63,7 @@ describe("audio_speech", () => { "nova", mockUpdateUI, "tts-1-hd", - "sk-1234567890", + "sk-9876543210", ["tag1", "tag2"], signal, "mp3", @@ -88,7 +88,7 @@ describe("audio_speech", () => { mockCreate.mockRejectedValue(mockError); await expect( - makeOpenAIAudioSpeechRequest("Hello, world!", "alloy", mockUpdateUI, "tts-1", "sk-1234567890", []), + makeOpenAIAudioSpeechRequest("Hello, world!", "alloy", mockUpdateUI, "tts-1", "sk-9876543210", []), ).rejects.toThrow("API Error"); expect(mockUpdateUI).not.toHaveBeenCalled(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_transcriptions.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_transcriptions.test.tsx index 52561e5d42e..c0c2a6e2a44 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_transcriptions.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/llm_calls/audio_transcriptions.test.tsx @@ -41,7 +41,7 @@ describe("audio_transcription", () => { type: "audio/wav", }); - await makeOpenAIAudioTranscriptionRequest(mockFile, mockUpdateUI, "whisper-1", "sk-1234567890", []); + await makeOpenAIAudioTranscriptionRequest(mockFile, mockUpdateUI, "whisper-1", "sk-9876543210", []); expect(mockCreate).toHaveBeenCalledWith( { @@ -64,7 +64,7 @@ describe("audio_transcription", () => { mockFile, mockUpdateUI, "whisper-1", - "sk-1234567890", + "sk-9876543210", ["tag1", "tag2"], signal, "en", @@ -95,7 +95,7 @@ describe("audio_transcription", () => { }); await expect( - makeOpenAIAudioTranscriptionRequest(mockFile, mockUpdateUI, "whisper-1", "sk-1234567890", []), + makeOpenAIAudioTranscriptionRequest(mockFile, mockUpdateUI, "whisper-1", "sk-9876543210", []), ).rejects.toThrow("API Error"); expect(mockUpdateUI).not.toHaveBeenCalled(); @@ -108,7 +108,7 @@ describe("audio_transcription", () => { }); await expect( - makeOpenAIAudioTranscriptionRequest(mockFile, mockUpdateUI, "whisper-1", "sk-1234567890", []), + makeOpenAIAudioTranscriptionRequest(mockFile, mockUpdateUI, "whisper-1", "sk-9876543210", []), ).rejects.toThrow("No transcription text in response"); expect(mockUpdateUI).not.toHaveBeenCalled(); diff --git a/ui/litellm-dashboard/src/app/login/LoginPage.integration.test.tsx b/ui/litellm-dashboard/src/app/login/LoginPage.integration.test.tsx index bfcc895e579..c463ab8f4aa 100644 --- a/ui/litellm-dashboard/src/app/login/LoginPage.integration.test.tsx +++ b/ui/litellm-dashboard/src/app/login/LoginPage.integration.test.tsx @@ -100,11 +100,11 @@ describe("LoginPage submit payload", () => { await screen.findByRole("heading", { name: "Login" }); fireEvent.change(screen.getByLabelText("Username"), { target: { value: "admin" } }); - fireEvent.change(screen.getByLabelText("Password"), { target: { value: "sk-1234" } }); + fireEvent.change(screen.getByLabelText("Password"), { target: { value: "sk-9876" } }); await user.click(screen.getByRole("button", { name: "Login" })); await waitFor(() => expect(mockMutate).toHaveBeenCalledTimes(1)); - expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-1234", useV3: false }); + expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-9876", useV3: false }); expect(switchToWorkerUrl).not.toHaveBeenCalled(); }); @@ -114,10 +114,10 @@ describe("LoginPage submit payload", () => { await screen.findByRole("heading", { name: "Login" }); fireEvent.change(screen.getByLabelText("Username"), { target: { value: "admin" } }); - await user.type(screen.getByLabelText("Password"), "sk-1234{Enter}"); + await user.type(screen.getByLabelText("Password"), "sk-9876{Enter}"); await waitFor(() => expect(mockMutate).toHaveBeenCalledTimes(1)); - expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-1234", useV3: false }); + expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-9876", useV3: false }); }); it("blocks submit and shows both required messages when the fields are empty", async () => { @@ -155,11 +155,11 @@ describe("LoginPage submit payload", () => { await user.click(screen.getAllByRole("combobox")[0]); await user.click(await screen.findByText("Worker B")); fireEvent.change(screen.getByLabelText("Username"), { target: { value: "admin" } }); - fireEvent.change(screen.getByLabelText("Password"), { target: { value: "sk-1234" } }); + fireEvent.change(screen.getByLabelText("Password"), { target: { value: "sk-9876" } }); await user.click(screen.getByRole("button", { name: "Login" })); await waitFor(() => expect(mockMutate).toHaveBeenCalledTimes(1)); - expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-1234", useV3: true }); + expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-9876", useV3: true }); expect(switchToWorkerUrl).toHaveBeenCalledWith("http://worker-b:4000"); }); @@ -182,11 +182,11 @@ describe("LoginPage submit payload", () => { await screen.findByRole("heading", { name: "Login" }); fireEvent.change(screen.getByLabelText("Username"), { target: { value: "admin" } }); - fireEvent.change(screen.getByLabelText("Password"), { target: { value: "sk-1234" } }); + fireEvent.change(screen.getByLabelText("Password"), { target: { value: "sk-9876" } }); await user.click(screen.getByRole("button", { name: "Login" })); await waitFor(() => expect(mockMutate).toHaveBeenCalledTimes(1)); - expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-1234", useV3: true }); + expect(mockMutate.mock.calls[0][0]).toStrictEqual({ username: "admin", password: "sk-9876", useV3: true }); expect(switchToWorkerUrl).toHaveBeenCalledWith("http://worker-a:4000"); }); }); diff --git a/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.test.tsx b/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.test.tsx index cf0c13ee152..0d9a5b8cc89 100644 --- a/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.test.tsx +++ b/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.test.tsx @@ -14,7 +14,7 @@ vi.mock("@/app/(dashboard)/hooks/keys/useKeys", () => ({ const mockUseDeletedKeys = useDeletedKeys as MockedFunction; const mockDeletedKey: DeletedKeyResponse = { - token: "sk-1234567890abcdef", + token: "sk-9876543210fedcba", token_id: "key-1", key_type: "llm_api", project_id: null, @@ -64,7 +64,7 @@ const mockDeletedKey: DeletedKeyResponse = { end_user_rpm_limit: 10, end_user_max_budget: 10, last_refreshed_at: Date.now(), - api_key: "sk-1234567890abcdef", + api_key: "sk-9876543210fedcba", user_role: "user", rpm_limit_per_model: {}, tpm_limit_per_model: {}, diff --git a/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysTable/DeletedKeysTable.test.tsx b/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysTable/DeletedKeysTable.test.tsx index dd8007be264..679af8b5bc4 100644 --- a/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysTable/DeletedKeysTable.test.tsx +++ b/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysTable/DeletedKeysTable.test.tsx @@ -9,7 +9,7 @@ vi.mock("next/navigation", () => ({ useRouter: () => ({ push: vi.fn() }) })); const makeDeletedKey = (overrides: Partial = {}): DeletedKeyResponse => ({ - token: "sk-1234567890abcdef", + token: "sk-9876543210fedcba", token_id: "key-1", key_name: "test-key", key_alias: "Test Key Alias", @@ -45,7 +45,7 @@ it("should display key information", () => { renderWithProviders(); expect(screen.getByText("Test Key Alias")).toBeInTheDocument(); - expect(screen.getByText("sk-1234567890abcdef")).toBeInTheDocument(); + expect(screen.getByText("sk-9876543210fedcba")).toBeInTheDocument(); expect(screen.getByText("user@example.com")).toBeInTheDocument(); }); diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterTestPanel.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterTestPanel.test.tsx index 2362f5ead60..95baa95da75 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterTestPanel.test.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterTestPanel.test.tsx @@ -151,7 +151,8 @@ describe("MCPSemanticFilterTestPanel", () => { it("should show the curl command in the API Usage tab", async () => { const user = userEvent.setup(); - const curlCommand = "curl --location 'http://localhost:4000/v1/responses' --header 'Authorization: Bearer sk-1234'"; + const curlCommand = + 'curl --location "http://localhost:4000/v1/responses" --header "Authorization: Bearer $LITELLM_MASTER_KEY"'; render(); await user.click(screen.getByRole("tab", { name: "API Usage" })); diff --git a/ui/litellm-dashboard/src/components/UsagePage/components/EntityUsage/TopKeyView.test.tsx b/ui/litellm-dashboard/src/components/UsagePage/components/EntityUsage/TopKeyView.test.tsx index e65094c5228..a46d31de848 100644 --- a/ui/litellm-dashboard/src/components/UsagePage/components/EntityUsage/TopKeyView.test.tsx +++ b/ui/litellm-dashboard/src/components/UsagePage/components/EntityUsage/TopKeyView.test.tsx @@ -253,7 +253,7 @@ describe("TopKeyView", () => { {...baseProps} topKeys={[ { - api_key: "sk-1234567890abcdef", + api_key: "sk-9876543210fedcba", key_alias: "Test Key", user: null, spend: 100, @@ -261,7 +261,7 @@ describe("TopKeyView", () => { ]} />, ); - const keyId = screen.getByText("sk-1234567890abcdef"); + const keyId = screen.getByText("sk-9876543210fedcba"); expect(keyId).toBeInTheDocument(); expect(keyId).toHaveClass("truncate"); }); diff --git a/ui/litellm-dashboard/src/components/routing_groups/RoutingGroupUsagePanel.tsx b/ui/litellm-dashboard/src/components/routing_groups/RoutingGroupUsagePanel.tsx index 85dd67099d6..0ad4d7bb08f 100644 --- a/ui/litellm-dashboard/src/components/routing_groups/RoutingGroupUsagePanel.tsx +++ b/ui/litellm-dashboard/src/components/routing_groups/RoutingGroupUsagePanel.tsx @@ -20,17 +20,18 @@ const exampleModel = (group: RoutingGroup): string => const buildCurlSnippet = (group: RoutingGroup, baseUrl: string): string => `curl -X POST '${baseUrl}/v1/chat/completions' \\ -H 'Content-Type: application/json' \\ - -H 'Authorization: Bearer $LITELLM_API_KEY' \\ + -H "Authorization: Bearer $LITELLM_API_KEY" \\ -d '{ "model": "${exampleModel(group)}", "messages": [{"role": "user", "content": "Hello!"}] }'`; const buildPythonSnippet = (group: RoutingGroup, baseUrl: string): string => - `from openai import OpenAI + `import os +from openai import OpenAI client = OpenAI( - api_key="$LITELLM_API_KEY", + api_key=os.environ["LITELLM_API_KEY"], base_url="${baseUrl}", ) diff --git a/ui/litellm-dashboard/src/components/shared/table_cells/id_cell.test.tsx b/ui/litellm-dashboard/src/components/shared/table_cells/id_cell.test.tsx index c6720ecc7b1..f61879d4789 100644 --- a/ui/litellm-dashboard/src/components/shared/table_cells/id_cell.test.tsx +++ b/ui/litellm-dashboard/src/components/shared/table_cells/id_cell.test.tsx @@ -27,8 +27,8 @@ describe("IdCell", () => { }); it("renders the full id as a non-interactive pill by default", () => { - render(); - const el = screen.getByText("sk-1234567890abcdef"); + render(); + const el = screen.getByText("sk-9876543210fedcba"); expect(el.tagName).toBe("SPAN"); expect(el).toHaveClass("bg-info/10"); expect(el).toHaveClass("font-mono"); diff --git a/ui/litellm-dashboard/src/components/templates/KeyInfoHeader.test.tsx b/ui/litellm-dashboard/src/components/templates/KeyInfoHeader.test.tsx index cc876758f74..1cb9ec79214 100644 --- a/ui/litellm-dashboard/src/components/templates/KeyInfoHeader.test.tsx +++ b/ui/litellm-dashboard/src/components/templates/KeyInfoHeader.test.tsx @@ -7,7 +7,7 @@ vi.mock("next/navigation", () => ({ useRouter: () => ({ push: vi.fn() }) })); const MOCK_DATA: KeyInfoData = { keyName: "My Test Key", - keyId: "sk-1234567890abcdef", + keyId: "sk-9876543210fedcba", userId: "user-abc-123", userEmail: "test@example.com", userAlias: null, @@ -32,7 +32,7 @@ describe("KeyInfoHeader", () => { it("should render the key ID with prefix", () => { render(); expect(screen.getByText(/Key ID:/)).toBeInTheDocument(); - expect(screen.getByText(/sk-1234567890abcdef/)).toBeInTheDocument(); + expect(screen.getByText(/sk-9876543210fedcba/)).toBeInTheDocument(); }); it("should render all metadata fields", () => { diff --git a/ui/litellm-dashboard/src/lib/http/schema.d.ts b/ui/litellm-dashboard/src/lib/http/schema.d.ts index e4d9111ab7a..b2d625cb5dd 100644 --- a/ui/litellm-dashboard/src/lib/http/schema.d.ts +++ b/ui/litellm-dashboard/src/lib/http/schema.d.ts @@ -469,7 +469,7 @@ export interface paths { * Example: * ```bash * curl -X GET 'http://localhost:4000/access_group/list' \ - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Returns: @@ -503,7 +503,7 @@ export interface paths { * Example: * ```bash * curl -X POST 'http://localhost:4000/access_group/new' \ - * -H 'Authorization: Bearer sk-1234' \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H 'Content-Type: application/json' \ * -d '{ * "access_group": "production-models", @@ -543,7 +543,7 @@ export interface paths { * Example: * ```bash * curl -X GET 'http://localhost:4000/access_group/production-models/budget' \ - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Parameters: @@ -565,7 +565,7 @@ export interface paths { * Example: * ```bash * curl -X PUT 'http://localhost:4000/access_group/production-models/budget' \ - * -H 'Authorization: Bearer sk-1234' \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H 'Content-Type: application/json' \ * -d '{ * "max_budget": 100.0, @@ -596,7 +596,7 @@ export interface paths { * Example: * ```bash * curl -X DELETE 'http://localhost:4000/access_group/production-models/budget' \ - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Parameters: @@ -633,7 +633,7 @@ export interface paths { * Example: * ```bash * curl -X DELETE 'http://localhost:4000/access_group/production-models/delete' \ - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Parameters: @@ -665,7 +665,7 @@ export interface paths { * Example: * ```bash * curl -X GET 'http://localhost:4000/access_group/production-models/info' \ - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Parameters: @@ -705,7 +705,7 @@ export interface paths { * Example: * ```bash * curl -X PUT 'http://localhost:4000/access_group/production-models/update' \ - * -H 'Authorization: Bearer sk-1234' \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H 'Content-Type: application/json' \ * -d '{ * "model_names": ["gpt-4", "claude-3-sonnet"] @@ -1807,7 +1807,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches?limit=2 -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" + * curl http://localhost:4000/v1/batches?limit=2 -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" * ``` */ get: operations["list_batches_batches_get"]; @@ -1820,7 +1820,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl http://localhost:4000/v1/batches -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "input_file_id": "file-abc123", * "endpoint": "/v1/chat/completions", * "completion_window": "24h" @@ -1849,7 +1849,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches/batch_abc123 -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" + * curl http://localhost:4000/v1/batches/batch_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" * ``` */ get: operations["retrieve_batch_batches__batch_id__get"]; @@ -1879,7 +1879,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches/batch_abc123/cancel -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -X POST + * curl http://localhost:4000/v1/batches/batch_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -X POST * * ``` */ @@ -2125,7 +2125,7 @@ export interface paths { * - **keys**: *Optional[List[str]]* - A list of keys to delete from the cache. Example {"keys": ["key1", "key2"]} * * ```shell - * curl -X POST "http://0.0.0.0:4000/cache/delete" -H "Authorization: Bearer sk-1234" -d '{"keys": ["key1", "key2"]}' + * curl -X POST "http://0.0.0.0:4000/cache/delete" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{"keys": ["key1", "key2"]}' * ``` */ post: operations["cache_delete_cache_delete_post"]; @@ -2152,7 +2152,7 @@ export interface paths { * * Usage: * ``` - * curl -X POST http://0.0.0.0:4000/cache/flushall -H "Authorization: Bearer sk-1234" + * curl -X POST http://0.0.0.0:4000/cache/flushall -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ post: operations["cache_flushall_cache_flushall_post"]; @@ -2350,7 +2350,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/chat/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-4o", * "messages": [ @@ -2807,7 +2807,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-3.5-turbo-instruct", * "prompt": "Once upon a time", @@ -3371,12 +3371,12 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/containers?limit=20&order=desc" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/containers?limit=20&order=desc" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Or specify provider via header or query param: * ```bash - * curl -X GET "http://localhost:4000/v1/containers?custom_llm_provider=azure" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/containers?custom_llm_provider=azure" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_containers_containers_get"]; @@ -3390,7 +3390,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "name": "My Container", * "expires_after": { * "anchor": "last_active_at", @@ -3401,7 +3401,7 @@ export interface paths { * * Or specify provider via header: * ```bash - * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer sk-1234" -H "custom-llm-provider: azure" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "custom-llm-provider: azure" -H "Content-Type: application/json" -d '{ * "name": "My Container" * }' * ``` @@ -3429,12 +3429,12 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Or specify provider via header: * ```bash - * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" -H "custom-llm-provider: azure" + * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "custom-llm-provider: azure" * ``` */ get: operations["retrieve_container_containers__container_id__get"]; @@ -3449,12 +3449,12 @@ export interface paths { * * Example: * ```bash - * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" + * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Or specify provider via header: * ```bash - * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" -H "custom-llm-provider: azure" + * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "custom-llm-provider: azure" * ``` */ delete: operations["delete_container_containers__container_id__delete"]; @@ -3859,7 +3859,7 @@ export interface paths { * Cursor already sent pre-nested. * * ```bash - * curl -X POST http://localhost:4000/cursor/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/cursor/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": [{"role": "user", "content": "Hello"}] * }' @@ -4076,7 +4076,7 @@ export interface paths { * * ``` * curl -X POST "http://0.0.0.0:8000/user/block" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "user_ids": [, ...] * }' @@ -4212,7 +4212,7 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/customer/delete' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/customer/delete' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_ids" :["ishaan-jaff-5"] * }' * @@ -4242,7 +4242,7 @@ export interface paths { * * Example curl: * ``` - * curl -X GET 'http://localhost:4000/customer/info?end_user_id=test-litellm-user-4' -H 'Authorization: Bearer sk-1234' + * curl -X GET 'http://localhost:4000/customer/info?end_user_id=test-litellm-user-4' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["end_user_info_customer_info_get"]; @@ -4267,7 +4267,7 @@ export interface paths { * * Example curl: * ``` - * curl --location --request GET 'http://0.0.0.0:4000/customer/list' --header 'Authorization: Bearer sk-1234' + * curl --location --request GET 'http://0.0.0.0:4000/customer/list' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_end_user_customer_list_get"]; @@ -4329,7 +4329,7 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/customer/new' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/customer/new' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_id" : "ishaan-jaff-3", * "allowed_region": "eu", * "budget_id": "free_tier", @@ -4338,7 +4338,7 @@ export interface paths { * }' * * # With object permissions - * curl -L -X POST 'http://localhost:4000/customer/new' -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' -d '{ + * curl -L -X POST 'http://localhost:4000/customer/new' -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d '{ * "user_id": "user_1", * "object_permission": { * "mcp_servers": ["server_1"], @@ -4375,7 +4375,7 @@ export interface paths { * Example * ``` * curl -X POST "http://0.0.0.0:8000/user/unblock" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "user_ids": [, ...] * }' @@ -4427,14 +4427,14 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/customer/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/customer/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_id": "test-litellm-user-4", * "budget_id": "paid_tier", * "models": ["gpt-4o-mini"] * }' * * # Updating object permissions - * curl -L -X POST 'http://localhost:4000/customer/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl -L -X POST 'http://localhost:4000/customer/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_id": "user_1", * "object_permission": { * "mcp_servers": ["server_3"], @@ -4499,7 +4499,7 @@ export interface paths { * - include_process_info: Include process-level memory info using psutil (default: true) * * Example usage: - * curl "http://localhost:4000/debug/memory/details?top_n=30" -H "Authorization: Bearer sk-1234" + * curl "http://localhost:4000/debug/memory/details?top_n=30" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * All memory sizes are reported in both bytes and MB. */ @@ -4541,10 +4541,10 @@ export interface paths { * - generation_2: Number of gen-1 collections before gen-2 collection (default: 10) * * Example for more aggressive collection: - * curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=500" -H "Authorization: Bearer sk-1234" + * curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=500" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * Example for less aggressive collection: - * curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=1000" -H "Authorization: Bearer sk-1234" + * curl -X POST "http://localhost:4000/debug/memory/gc/configure?generation_0=1000" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * Monitor memory usage with GET /debug/memory/summary after changes. */ @@ -4575,7 +4575,7 @@ export interface paths { * - garbage_collector: GC status and pending object counts * * Example usage: - * curl http://localhost:4000/debug/memory/summary -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/debug/memory/summary -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * For detailed analysis, call GET /debug/memory/details * For cache management, use the cache management endpoints @@ -4603,7 +4603,7 @@ export interface paths { * Nothing from the operator's config values, request data, or errors * * Example usage: - * curl http://localhost:4000/debug/report -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/debug/report -H "Authorization: Bearer $LITELLM_MASTER_KEY" */ get: operations["get_debug_report_debug_report_get"]; put?: never; @@ -4708,7 +4708,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/embeddings * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "text-embedding-ada-002", * "input": "The quick brown fox jumps over the lazy dog" @@ -4742,7 +4742,7 @@ export interface paths { * * ``` * curl -X POST "http://0.0.0.0:8000/user/block" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "user_ids": [, ...] * }' @@ -4878,7 +4878,7 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/customer/delete' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/customer/delete' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_ids" :["ishaan-jaff-5"] * }' * @@ -4908,7 +4908,7 @@ export interface paths { * * Example curl: * ``` - * curl -X GET 'http://localhost:4000/customer/info?end_user_id=test-litellm-user-4' -H 'Authorization: Bearer sk-1234' + * curl -X GET 'http://localhost:4000/customer/info?end_user_id=test-litellm-user-4' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["end_user_info_end_user_info_get"]; @@ -4933,7 +4933,7 @@ export interface paths { * * Example curl: * ``` - * curl --location --request GET 'http://0.0.0.0:4000/customer/list' --header 'Authorization: Bearer sk-1234' + * curl --location --request GET 'http://0.0.0.0:4000/customer/list' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_end_user_end_user_list_get"]; @@ -4995,7 +4995,7 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/customer/new' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/customer/new' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_id" : "ishaan-jaff-3", * "allowed_region": "eu", * "budget_id": "free_tier", @@ -5004,7 +5004,7 @@ export interface paths { * }' * * # With object permissions - * curl -L -X POST 'http://localhost:4000/customer/new' -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' -d '{ + * curl -L -X POST 'http://localhost:4000/customer/new' -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d '{ * "user_id": "user_1", * "object_permission": { * "mcp_servers": ["server_1"], @@ -5041,7 +5041,7 @@ export interface paths { * Example * ``` * curl -X POST "http://0.0.0.0:8000/user/unblock" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "user_ids": [, ...] * }' @@ -5093,14 +5093,14 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/customer/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/customer/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_id": "test-litellm-user-4", * "budget_id": "paid_tier", * "models": ["gpt-4o-mini"] * }' * * # Updating object permissions - * curl -L -X POST 'http://localhost:4000/customer/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl -L -X POST 'http://localhost:4000/customer/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_id": "user_1", * "object_permission": { * "mcp_servers": ["server_3"], @@ -5134,7 +5134,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/chat/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-4o", * "messages": [ @@ -5169,7 +5169,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-3.5-turbo-instruct", * "prompt": "Once upon a time", @@ -5201,7 +5201,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/embeddings * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "text-embedding-ada-002", * "input": "The quick brown fox jumps over the lazy dog" @@ -5374,7 +5374,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -5389,7 +5389,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files -H "Authorization: Bearer sk-1234" -F purpose="batch" -F file="@mydata.jsonl" + * curl http://localhost:4000/v1/files -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F purpose="batch" -F file="@mydata.jsonl" * -F expires_after[anchor]="created_at" -F expires_after[seconds]=2592000 * ``` */ @@ -5416,7 +5416,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files/file-abc123 -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files/file-abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -5458,7 +5458,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files/file-abc123/content -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files/file-abc123/content -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -5499,7 +5499,7 @@ export interface paths { * * Example Curl: * ``` - * curl http://localhost:4000/v1/fine_tuning/jobs -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl http://localhost:4000/v1/fine_tuning/jobs -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-3.5-turbo", * "training_file": "file-abc123", * "hyperparameters": { @@ -6483,12 +6483,12 @@ export interface paths { * * Example Request: * ``` - * curl -X GET "http://0.0.0.0:4000/spend/tags" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:4000/spend/tags" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Spend with Start Date and End Date * ``` - * curl -X GET "http://0.0.0.0:4000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:4000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["global_view_spend_tags_global_spend_tags_get"]; @@ -7613,7 +7613,7 @@ export interface paths { * * Example: * ``` - * curl -L -X GET 'http://0.0.0.0:4000/health/services?service=datadog' -H 'Authorization: Bearer sk-1234' + * curl -L -X GET 'http://0.0.0.0:4000/health/services?service=datadog' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["health_services_endpoint_health_services_get"]; @@ -7667,7 +7667,7 @@ export interface paths { * ```bash * # If model is configured in proxy_config.yaml, you only need to specify the model name: * curl -X POST 'http://localhost:4000/health/test_connection' \ - * -H 'Authorization: Bearer sk-1234' \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H 'Content-Type: application/json' \ * -d '{ * "litellm_params": { @@ -7680,7 +7680,7 @@ export interface paths { * * # You can also override specific params or test with custom credentials: * curl -X POST 'http://localhost:4000/health/test_connection' \ - * -H 'Authorization: Bearer sk-1234' \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H 'Content-Type: application/json' \ * -d '{ * "litellm_params": { @@ -7727,7 +7727,7 @@ export interface paths { * @description Follows the OpenAI Images API spec: https://platform.openai.com/docs/api-reference/images/create * * ```bash - * curl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST "http://localhost:4000/v1/images/edits" -H "Authorization: Bearer sk-1234" -F "model=gpt-image-1" -F "image[]=@soap.png" -F 'prompt=Create a studio ghibli image of this' + * curl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST "http://localhost:4000/v1/images/edits" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F "model=gpt-image-1" -F "image[]=@soap.png" -F 'prompt=Create a studio ghibli image of this' * ``` */ post: operations["image_edit_api_images_edits_post"]; @@ -7775,7 +7775,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1beta/interactions" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1beta/interactions" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "model": "gemini/gemini-2.5-flash", * "input": "Hello, how are you?" * }' @@ -8102,7 +8102,7 @@ export interface paths { * * Example: * ```bash - * curl --location 'http://0.0.0.0:4000/key/block' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/key/block' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "key": "sk-Fn8Ej39NxjAXrvpUGKghGw" * }' * ``` @@ -8151,10 +8151,10 @@ export interface paths { * * Example request: * ```bash - * curl --location 'http://0.0.0.0:4000/key/bulk_update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/key/bulk_update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "keys": [ * { - * "key": "sk-1234", + * "key": "sk-", * "max_budget": 100.0, * "team_id": "team-123", * "tags": ["production", "api"] @@ -8197,7 +8197,7 @@ export interface paths { * * Example: * ```bash - * curl --location 'http://0.0.0.0:4000/key/delete' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/key/delete' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "keys": ["sk-QWrxEynunsNpV1zT48HIrw"] * }' * ``` @@ -8290,7 +8290,7 @@ export interface paths { * 1. Allow users to turn on/off pii masking * * ```bash - * curl --location 'http://0.0.0.0:4000/key/generate' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/key/generate' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "permissions": {"allow_pii_controls": true} * }' * ``` @@ -8328,7 +8328,7 @@ export interface paths { * Pass the key in the request header * * ```bash - * curl -X POST "http://localhost:4000/key/health" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" + * curl -X POST "http://localhost:4000/key/health" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" * ``` * * Response when logging callbacks are setup correctly: @@ -8417,7 +8417,7 @@ export interface paths { * * Example Curl: * ``` - * curl -X GET "http://0.0.0.0:4000/key/info?key=d5345c0ecc68ae6295c69f91926b2bd379e25481a40c34b5884d157a9f65d8fa" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:4000/key/info?key=d5345c0ecc68ae6295c69f91926b2bd379e25481a40c34b5884d157a9f65d8fa" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example Curl - if no key is passed, it will use the Key Passed in Authorization Header @@ -8520,7 +8520,7 @@ export interface paths { * * Example: * ```bash - * curl --location --request POST 'http://localhost:4000/key/sk-1234/regenerate' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data-raw '{ + * curl --location --request POST "http://localhost:4000/key/$LITELLM_API_KEY/regenerate" --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data-raw '{ * "max_budget": 100, * "metadata": {"team": "core-infra"}, * "models": ["gpt-4", "gpt-3.5-turbo"] @@ -8600,7 +8600,7 @@ export interface paths { * 1. Allow users to turn on/off pii masking * * ```bash - * curl --location 'http://0.0.0.0:4000/key/generate' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/key/generate' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "permissions": {"allow_pii_controls": true} * }' * ``` @@ -8659,7 +8659,7 @@ export interface paths { * * Example: * ```bash - * curl --location 'http://0.0.0.0:4000/key/unblock' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/key/unblock' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "key": "sk-Fn8Ej39NxjAXrvpUGKghGw" * }' * ``` @@ -8752,8 +8752,8 @@ export interface paths { * * Example: * ```bash - * curl --location 'http://0.0.0.0:4000/key/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ - * "key": "sk-1234", + * curl --location 'http://0.0.0.0:4000/key/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ + * "key": "sk-", * "key_alias": "my-key", * "user_id": "user-1234", * "team_id": "team-1234", @@ -8818,7 +8818,7 @@ export interface paths { * * Example: * ```bash - * curl --location --request POST 'http://localhost:4000/key/sk-1234/regenerate' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data-raw '{ + * curl --location --request POST "http://localhost:4000/key/$LITELLM_API_KEY/regenerate" --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data-raw '{ * "max_budget": 100, * "metadata": {"team": "core-infra"}, * "models": ["gpt-4", "gpt-3.5-turbo"] @@ -9403,7 +9403,7 @@ export interface paths { * * Example curl: * ``` - * curl --location --globoff 'http://0.0.0.0:4000/management/v1/budgets?sort=-max_budget&filter[budget_duration][in]=7d,30d&page_size=25' --header 'Authorization: Bearer sk-1234' + * curl --location --globoff 'http://0.0.0.0:4000/management/v1/budgets?sort=-max_budget&filter[budget_duration][in]=7d,30d&page_size=25' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_budgets_management_v1_budgets_get"]; @@ -9437,7 +9437,7 @@ export interface paths { * * Example curl: * ``` - * curl --location --globoff 'http://0.0.0.0:4000/management/v1/spend_logs/end_users?filter[startTime][gte]=2026-07-23T00:00:00Z&filter[startTime][lte]=2026-07-24T00:00:00Z&page_size=50&q=acme' --header 'Authorization: Bearer sk-1234' + * curl --location --globoff 'http://0.0.0.0:4000/management/v1/spend_logs/end_users?filter[startTime][gte]=2026-07-23T00:00:00Z&filter[startTime][lte]=2026-07-24T00:00:00Z&page_size=50&q=acme' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_spend_log_end_users_management_v1_spend_logs_end_users_get"]; @@ -9492,7 +9492,7 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/management/v1/teams/team-1/members/bulk_delete' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{"members": [{"user_id": "user-1"}, {"user_email": "user-2@example.com"}]}' + * curl --location 'http://0.0.0.0:4000/management/v1/teams/team-1/members/bulk_delete' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{"members": [{"user_id": "user-1"}, {"user_email": "user-2@example.com"}]}' * ``` */ post: operations["bulk_delete_team_members_action_management_v1_teams__team_id__members_bulk_delete_post"]; @@ -9531,7 +9531,7 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/management/v1/teams/team-1/members/bulk_update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{"members": [{"user_id": "user-1", "max_budget_in_team": 10}, {"user_email": "user-2@example.com", "max_budget_in_team": 10, "budget_duration": "30d"}]}' + * curl --location 'http://0.0.0.0:4000/management/v1/teams/team-1/members/bulk_update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{"members": [{"user_id": "user-1", "max_budget_in_team": 10}, {"user_email": "user-2@example.com", "max_budget_in_team": 10, "budget_duration": "30d"}]}' * ``` */ post: operations["bulk_update_team_member_budgets_action_management_v1_teams__team_id__members_bulk_update_post"]; @@ -9570,7 +9570,7 @@ export interface paths { * ``` * curl -X POST "http://localhost:4000/management/v1/users/bulk" \ * -H "Content-Type: application/json" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -d '{ * "users": [ * {"user_email": "a@example.com", "user_role": "internal_user", "teams": ["team-1"]}, @@ -9611,7 +9611,7 @@ export interface paths { * * Example curl: * ``` - * curl --location 'http://0.0.0.0:4000/management/v1/users/bulk_delete' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{"user_ids": ["user-1", "user-2"]}' + * curl --location 'http://0.0.0.0:4000/management/v1/users/bulk_delete' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{"user_ids": ["user-1", "user-2"]}' * ``` */ post: operations["bulk_delete_users_action_management_v1_users_bulk_delete_post"]; @@ -10079,7 +10079,7 @@ export interface paths { * Example: * ```shell * curl -X GET 'http://localhost:4000/model/deprecations' \ - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["model_deprecations_model_deprecations_get"]; @@ -10369,18 +10369,18 @@ export interface paths { * * Example Request (All Models): * ```shell - * curl -X 'GET' 'http://localhost:4000/model_group/info' -H 'accept: application/json' -H 'x-api-key: sk-1234' + * curl -X 'GET' 'http://localhost:4000/model_group/info' -H 'accept: application/json' -H "x-api-key: $LITELLM_MASTER_KEY" * ``` * * Example Request (Specific Model Group): * ```shell - * curl -X 'GET' 'http://localhost:4000/model_group/info?model_group=rerank-english-v3.0' -H 'accept: application/json' -H 'Authorization: Bearer sk-1234' + * curl -X 'GET' 'http://localhost:4000/model_group/info?model_group=rerank-english-v3.0' -H 'accept: application/json' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example Request (Specific Wildcard Model Group): (e.g. `model_name: openai/*` on config.yaml) * ```shell * curl -X 'GET' 'http://localhost:4000/model_group/info?model_group=openai/tts-1' - * -H 'accept: application/json' -H 'Authorization: Bearersk-1234' + * -H 'accept: application/json' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Learn how to use and set wildcard models [here](https://docs.litellm.ai/docs/wildcard_routing) @@ -10707,7 +10707,7 @@ export interface paths { * @description The moderations endpoint is a tool you can use to check whether content complies with an LLM Providers policies. * Quick Start * ``` - * curl --location 'http://0.0.0.0:4000/moderations' --header 'Content-Type: application/json' --header 'Authorization: Bearer sk-1234' --data '{"input": "Sample text goes here", "model": "text-moderation-stable"}' + * curl --location 'http://0.0.0.0:4000/moderations' --header 'Content-Type: application/json' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --data '{"input": "Sample text goes here", "model": "text-moderation-stable"}' * ``` */ post: operations["moderations_moderations_post"]; @@ -10790,7 +10790,7 @@ export interface paths { * * **1. JSON body** (Mistral OCR API compatible): * ```bash - * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "model": "mistral-ocr", * "document": { * "type": "document_url", @@ -10801,7 +10801,7 @@ export interface paths { * * **2. Multipart form file upload**: * ```bash - * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer sk-1234" -F "model=mistral-ocr" -F "file=@document.pdf" + * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F "model=mistral-ocr" -F "file=@document.pdf" * ``` * * Response format is normalized to the LiteLLM OCR schema by default. Providers @@ -10884,7 +10884,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/chat/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-4o", * "messages": [ @@ -10919,7 +10919,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-3.5-turbo-instruct", * "prompt": "Once upon a time", @@ -10951,7 +10951,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/embeddings * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "text-embedding-ada-002", * "input": "The quick brown fox jumps over the lazy dog" @@ -10979,7 +10979,7 @@ export interface paths { * @description Follows the OpenAI Images API spec: https://platform.openai.com/docs/api-reference/images/create * * ```bash - * curl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST "http://localhost:4000/v1/images/edits" -H "Authorization: Bearer sk-1234" -F "model=gpt-image-1" -F "image[]=@soap.png" -F 'prompt=Create a studio ghibli image of this' + * curl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST "http://localhost:4000/v1/images/edits" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F "model=gpt-image-1" -F "image[]=@soap.png" -F 'prompt=Create a studio ghibli image of this' * ``` */ post: operations["image_edit_api_openai_deployments__model__images_edits_post"]; @@ -11103,13 +11103,13 @@ export interface paths { * * ```bash * # Normal request - * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Tell me about AI" * }' * * # Background request with polling - * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Tell me about AI", * "background": true @@ -11141,7 +11141,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/compact * * ```bash - * curl -X POST http://localhost:4000/v1/responses/compact -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses/compact -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": [{"role": "user", "content": "Hello"}] * }' @@ -11170,7 +11170,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/input-tokens * * ```bash - * curl -X POST http://localhost:4000/v1/responses/input_tokens -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses/input_tokens -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Hello, how are you?" * }' @@ -11204,10 +11204,10 @@ export interface paths { * * ```bash * # Get polling response - * curl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H "Authorization: Bearer sk-1234" + * curl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * # Get provider response - * curl -X GET http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer sk-1234" + * curl -X GET http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["get_response_openai_v1_responses__response_id__get"]; @@ -11224,7 +11224,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/delete * * ```bash - * curl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer sk-1234" + * curl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ delete: operations["delete_response_openai_v1_responses__response_id__delete"]; @@ -11254,10 +11254,10 @@ export interface paths { * * ```bash * # Cancel polling response - * curl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H "Authorization: Bearer sk-1234" + * curl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * # Cancel provider response - * curl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H "Authorization: Bearer sk-1234" + * curl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ post: operations["cancel_response_openai_v1_responses__response_id__cancel_post"]; @@ -11692,12 +11692,12 @@ export interface paths { * * Example: * ``` - * curl --location --request GET 'http://0.0.0.0:4000/organization/list?org_alias=my-org' --header 'Authorization: Bearer sk-1234' + * curl --location --request GET 'http://0.0.0.0:4000/organization/list?org_alias=my-org' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example with org_id: * ``` - * curl --location --request GET 'http://0.0.0.0:4000/organization/list?org_id=123e4567-e89b-12d3-a456-426614174000' --header 'Authorization: Bearer sk-1234' + * curl --location --request GET 'http://0.0.0.0:4000/organization/list?org_id=123e4567-e89b-12d3-a456-426614174000' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_organization_organization_list_get"]; @@ -11740,7 +11740,7 @@ export interface paths { * * Example: * ``` - * curl -X POST 'http://0.0.0.0:4000/organization/member_add' -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' -d '{ + * curl -X POST 'http://0.0.0.0:4000/organization/member_add' -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d '{ * "organization_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849", * "member": { * "role": "internal_user", @@ -11849,7 +11849,7 @@ export interface paths { * * ```bash * curl --location 'http://0.0.0.0:4000/organization/new' - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * --header 'Content-Type: application/json' * --data '{ * "organization_alias": "my-secret-org", @@ -11864,7 +11864,7 @@ export interface paths { * * ```bash * curl --location 'http://0.0.0.0:4000/organization/new' - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * --header 'Content-Type: application/json' * --data '{ * "organization_alias": "my-secret-org", @@ -12890,7 +12890,7 @@ export interface paths { * Example: * ```bash * curl --location --request DELETE 'http://0.0.0.0:4000/project/delete' \ - * --header 'Authorization: Bearer sk-1234' \ + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ * --header 'Content-Type: application/json' \ * --data '{ * "project_ids": ["project-123", "project-456"] @@ -12920,7 +12920,7 @@ export interface paths { * Example: * ```bash * curl --location 'http://0.0.0.0:4000/project/info?project_id=project-123' \ - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["project_info_project_info_get"]; @@ -12946,7 +12946,7 @@ export interface paths { * Example: * ```bash * curl --location 'http://0.0.0.0:4000/project/list' \ - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_projects_project_list_get"]; @@ -12999,7 +12999,7 @@ export interface paths { * * ```bash * curl --location 'http://0.0.0.0:4000/project/new' \ - * --header 'Authorization: Bearer sk-1234' \ + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ * --header 'Content-Type: application/json' \ * --data '{ * "project_alias": "flight-search-assistant", @@ -13026,7 +13026,7 @@ export interface paths { * * ```bash * curl --location 'http://0.0.0.0:4000/project/new' \ - * --header 'Authorization: Bearer sk-1234' \ + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ * --header 'Content-Type: application/json' \ * --data '{ * "project_alias": "hotel-recommendations", @@ -13080,7 +13080,7 @@ export interface paths { * Example: * ```bash * curl --location 'http://0.0.0.0:4000/project/update' \ - * --header 'Authorization: Bearer sk-1234' \ + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" \ * --header 'Content-Type: application/json' \ * --data '{ * "project_id": "project-123", @@ -13459,7 +13459,7 @@ export interface paths { * Example Request * * ```bash - * curl -X GET http://localhost:4000/provider/budgets -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" + * curl -X GET http://localhost:4000/provider/budgets -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example Response @@ -13879,7 +13879,7 @@ export interface paths { * ## Form upload (for files): * ```bash * curl -X POST "http://localhost:4000/v1/rag/ingest" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -F file="@document.pdf" \ * -F 'ingest_options={"vector_store": {"custom_llm_provider": "openai"}}' * ``` @@ -13887,7 +13887,7 @@ export interface paths { * ## JSON body (for URLs): * ```bash * curl -X POST "http://localhost:4000/v1/rag/ingest" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H "Content-Type: application/json" \ * -d '{ * "file_url": "https://example.com/document.pdf", @@ -13898,7 +13898,7 @@ export interface paths { * ## Bedrock: * ```bash * curl -X POST "http://localhost:4000/v1/rag/ingest" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -F file="@document.pdf" \ * -F 'ingest_options={"vector_store": {"custom_llm_provider": "bedrock"}}' * ``` @@ -13932,7 +13932,7 @@ export interface paths { * ## Example Request: * ```bash * curl -X POST "http://localhost:4000/v1/rag/query" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H "Content-Type: application/json" \ * -d '{ * "model": "gpt-4o-mini", @@ -13948,7 +13948,7 @@ export interface paths { * ## With Reranking: * ```bash * curl -X POST "http://localhost:4000/v1/rag/query" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H "Content-Type: application/json" \ * -d '{ * "model": "gpt-4o-mini", @@ -14154,13 +14154,13 @@ export interface paths { * * ```bash * # Normal request - * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Tell me about AI" * }' * * # Background request with polling - * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Tell me about AI", * "background": true @@ -14192,7 +14192,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/compact * * ```bash - * curl -X POST http://localhost:4000/v1/responses/compact -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses/compact -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": [{"role": "user", "content": "Hello"}] * }' @@ -14221,7 +14221,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/input-tokens * * ```bash - * curl -X POST http://localhost:4000/v1/responses/input_tokens -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses/input_tokens -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Hello, how are you?" * }' @@ -14255,10 +14255,10 @@ export interface paths { * * ```bash * # Get polling response - * curl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H "Authorization: Bearer sk-1234" + * curl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * # Get provider response - * curl -X GET http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer sk-1234" + * curl -X GET http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["get_response_responses__response_id__get"]; @@ -14275,7 +14275,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/delete * * ```bash - * curl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer sk-1234" + * curl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ delete: operations["delete_response_responses__response_id__delete"]; @@ -14305,10 +14305,10 @@ export interface paths { * * ```bash * # Cancel polling response - * curl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H "Authorization: Bearer sk-1234" + * curl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * # Cancel provider response - * curl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H "Authorization: Bearer sk-1234" + * curl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ post: operations["cancel_response_responses__response_id__cancel_post"]; @@ -14871,7 +14871,7 @@ export interface paths { * * Example with search_tool_name in URL (recommended - keeps body Perplexity-compatible): * ```bash - * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "query": "latest AI developments 2024", * "max_results": 5, * "search_domain_filter": ["arxiv.org", "nature.com"], @@ -14881,7 +14881,7 @@ export interface paths { * * Example with search_tool_name in body: * ```bash - * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "search_tool_name": "litellm-search", * "query": "latest AI developments 2024", * "max_results": 5, @@ -14944,7 +14944,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/search/tools" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/search/tools" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Response: @@ -14992,7 +14992,7 @@ export interface paths { * * Example with search_tool_name in URL (recommended - keeps body Perplexity-compatible): * ```bash - * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "query": "latest AI developments 2024", * "max_results": 5, * "search_domain_filter": ["arxiv.org", "nature.com"], @@ -15002,7 +15002,7 @@ export interface paths { * * Example with search_tool_name in body: * ```bash - * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "search_tool_name": "litellm-search", * "query": "latest AI developments 2024", * "max_results": 5, @@ -15444,7 +15444,7 @@ export interface paths { * * ``` * curl --location 'http://localhost:4000/spend/calculate' - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * --header 'Content-Type: application/json' * --data '{ * "model": "anthropic.claude-v2", @@ -15456,7 +15456,7 @@ export interface paths { * * ``` * curl --location 'http://localhost:4000/spend/calculate' - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * --header 'Content-Type: application/json' * --data '{ * "completion_response": { @@ -15506,7 +15506,7 @@ export interface paths { * * Example: * ``` - * curl -H "Authorization: Bearer sk-1234" "http://localhost:4000/spend/capture_rate?provider=openai&start_date=2026-09-17&end_date=2026-09-23" + * curl -H "Authorization: Bearer $LITELLM_MASTER_KEY" "http://localhost:4000/spend/capture_rate?provider=openai&start_date=2026-09-17&end_date=2026-09-23" * ``` */ get: operations["get_spend_capture_rate_spend_capture_rate_get"]; @@ -15538,7 +15538,7 @@ export interface paths { * * Example Request: * ``` - * curl -X GET "http://0.0.0.0:8000/spend/keys" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/keys" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["spend_key_fn_spend_keys_get"]; @@ -15572,27 +15572,27 @@ export interface paths { * * Example Request for all logs * ``` - * curl -X GET "http://0.0.0.0:8000/spend/logs" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/logs" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example Request for specific request_id * ``` - * curl -X GET "http://0.0.0.0:8000/spend/logs?request_id=chatcmpl-6dcb2540-d3d7-4e49-bb27-291f863f112e" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/logs?request_id=chatcmpl-6dcb2540-d3d7-4e49-bb27-291f863f112e" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example Request for specific api_key * ``` - * curl -X GET "http://0.0.0.0:8000/spend/logs?api_key=d5345c0ecc68ae6295c69f91926b2bd379e25481a40c34b5884d157a9f65d8fa" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/logs?api_key=d5345c0ecc68ae6295c69f91926b2bd379e25481a40c34b5884d157a9f65d8fa" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example Request for specific user_id * ``` - * curl -X GET "http://0.0.0.0:8000/spend/logs?user_id=ishaan@berri.ai" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/logs?user_id=ishaan@berri.ai" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example Request for date range with individual logs (unsummarized) * ``` - * curl -X GET "http://0.0.0.0:8000/spend/logs?start_date=2024-01-01&end_date=2024-01-02&summarize=false" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/logs?start_date=2024-01-01&end_date=2024-01-02&summarize=false" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["view_spend_logs_spend_logs_get"]; @@ -15649,7 +15649,7 @@ export interface paths { * * Example: * ``` - * curl -X GET "http://0.0.0.0:8000/spend/logs/v2?start_date=2025-11-25%2000:00:00&end_date=2025-11-26%2023:59:59&page=1&page_size=50" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/logs/v2?start_date=2025-11-25%2000:00:00&end_date=2025-11-26%2023:59:59&page=1&page_size=50" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["ui_view_spend_logs_spend_logs_ui_get"]; @@ -15700,7 +15700,7 @@ export interface paths { * * Example: * ``` - * curl -X GET "http://0.0.0.0:8000/spend/logs/v2?start_date=2025-11-25%2000:00:00&end_date=2025-11-26%2023:59:59&page=1&page_size=50" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/logs/v2?start_date=2025-11-25%2000:00:00&end_date=2025-11-26%2023:59:59&page=1&page_size=50" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["ui_view_spend_logs_spend_logs_v2_get"]; @@ -15725,12 +15725,12 @@ export interface paths { * * Example Request: * ``` - * curl -X GET "http://0.0.0.0:8000/spend/tags" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/tags" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Spend with Start Date and End Date * ``` - * curl -X GET "http://0.0.0.0:8000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["view_spend_tags_spend_tags_get"]; @@ -15764,12 +15764,12 @@ export interface paths { * * Example Request: * ``` - * curl -X GET "http://0.0.0.0:8000/spend/users" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/users" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * View User Table row for user_id * ``` - * curl -X GET "http://0.0.0.0:8000/spend/users?user_id=1234" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://0.0.0.0:8000/spend/users?user_id=1234" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["spend_user_fn_spend_users_get"]; @@ -16498,7 +16498,7 @@ export interface paths { * * Example: * ``` - * curl --location 'http://0.0.0.0:4000/team/block' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/team/block' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "team_id": "team-1234" * }' * ``` @@ -16543,7 +16543,7 @@ export interface paths { * * Example request: * ```bash - * curl --location 'http://0.0.0.0:4000/team/bulk_member_add' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/team/bulk_member_add' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "team_id": "team-1234", * "members": [ * { @@ -16718,7 +16718,7 @@ export interface paths { * - team_ids: List[str] - Required. List of team IDs to delete. Example: ["team-1234", "team-5678"] * * ``` - * curl --location 'http://0.0.0.0:4000/team/delete' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data-raw '{ + * curl --location 'http://0.0.0.0:4000/team/delete' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data-raw '{ * "team_ids": ["8d916b1c-510d-4894-a334-1c16a93344f5"] * }' * ``` @@ -16823,7 +16823,7 @@ export interface paths { /** * List Team * @description ``` - * curl --location --request GET 'http://0.0.0.0:4000/team/list' --header 'Authorization: Bearer sk-1234' + * curl --location --request GET 'http://0.0.0.0:4000/team/list' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Parameters: @@ -16857,7 +16857,7 @@ export interface paths { * Only proxy_admin or admin of team, allowed to access this endpoint. * ``` * - * curl -X POST 'http://0.0.0.0:4000/team/member_add' -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' -d '{"team_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849", "member": {"role": "user", "user_id": "krrish247652@berri.ai"}}' + * curl -X POST 'http://0.0.0.0:4000/team/member_add' -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d '{"team_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849", "member": {"role": "user", "user_id": "krrish247652@berri.ai"}}' * * ``` */ @@ -16886,7 +16886,7 @@ export interface paths { * If user doesn't exist, an exception will be raised * ``` * curl -X POST 'http://0.0.0.0:8000/team/member_delete' - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -H 'Content-Type: application/json' * -d '{ * "team_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849", @@ -16967,7 +16967,7 @@ export interface paths { * * Example Request: * ``` - * curl --location 'http://0.0.0.0:4000/team/model/add' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/team/model/add' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "team_id": "team-1234", * "models": ["gpt-4", "claude-2"] * }' @@ -16999,7 +16999,7 @@ export interface paths { * * Example Request: * ``` - * curl --location 'http://0.0.0.0:4000/team/model/delete' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/team/model/delete' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "team_id": "team-1234", * "models": ["gpt-4"] * }' @@ -17083,7 +17083,7 @@ export interface paths { * * Example Request: * ``` - * curl --location 'http://0.0.0.0:4000/team/new' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/team/new' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "team_alias": "my-new-team_2", * "members_with_roles": [{"role": "admin", "user_id": "user-1234"}, * {"role": "user", "user_id": "user-2434"}] @@ -17092,7 +17092,7 @@ export interface paths { * ``` * * ``` - * curl --location 'http://0.0.0.0:4000/team/new' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/team/new' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "team_alias": "QA Prod Bot", * "max_budget": 0.000000001, * "budget_duration": "1d" @@ -17237,7 +17237,7 @@ export interface paths { * * Example: * ``` - * curl --location 'http://0.0.0.0:4000/team/unblock' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/team/unblock' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "team_id": "team-1234" * }' * ``` @@ -17308,7 +17308,7 @@ export interface paths { * - default_team_member_models: Optional[List[str]] - Default models assigned to new team members when they join this team. Must be a subset of the team's models. * * ``` - * curl --location 'http://0.0.0.0:4000/team/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data-raw '{ + * curl --location 'http://0.0.0.0:4000/team/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data-raw '{ * "team_id": "8d916b1c-510d-4894-a334-1c16a93344f5", * "tpm_limit": 100 * }' @@ -17316,7 +17316,7 @@ export interface paths { * * Example - Update Team `max_budget` budget * ``` - * curl --location 'http://0.0.0.0:4000/team/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data-raw '{ + * curl --location 'http://0.0.0.0:4000/team/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data-raw '{ * "team_id": "8d916b1c-510d-4894-a334-1c16a93344f5", * "max_budget": 10 * }' @@ -17354,7 +17354,7 @@ export interface paths { * updated team. * * ``` - * curl --location --request PATCH 'http://0.0.0.0:4000/team/8d916b1c-510d-4894-a334-1c16a93344f5' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data-raw '{ + * curl --location --request PATCH 'http://0.0.0.0:4000/team/8d916b1c-510d-4894-a334-1c16a93344f5' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data-raw '{ * "metadata": {"cost_center": "1234", "deprecated_key": null} * }' * ``` @@ -17378,7 +17378,7 @@ export interface paths { * * Example curl: * ``` - * curl -X GET 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback' -H 'Authorization: Bearer sk-1234' + * curl -X GET 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * This will return the callback settings for the team with id dbe2f686-a686-4896-864a-4c3924458709 @@ -17430,7 +17430,7 @@ export interface paths { * * Example curl: * ``` - * curl -X POST 'http:/localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback' -H 'Content-Type: application/json' -H 'Authorization: Bearer sk-1234' -d '{ + * curl -X POST 'http:/localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback' -H 'Content-Type: application/json' -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "callback_name": "langfuse", * "callback_type": "success", * "callback_vars": {"langfuse_public_key": "pk-lf-xxxx1", "langfuse_secret_key": "sk-xxxxx"} @@ -17474,7 +17474,7 @@ export interface paths { * * Example curl: * ``` - * curl -X DELETE 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback/langsmith' -H 'Authorization: Bearer sk-1234' + * curl -X DELETE 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/callback/langsmith' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Covers callbacks registered through POST /team/{team_id}/callback and the Admin UI. Teams still @@ -17510,7 +17510,7 @@ export interface paths { * * Example curl: * ``` - * curl -X POST 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/disable_logging' -H 'Authorization: Bearer sk-1234' + * curl -X POST 'http://localhost:4000/team/dbe2f686-a686-4896-864a-4c3924458709/disable_logging' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ post: operations["disable_team_logging_team__team_id__disable_logging_post"]; @@ -18284,7 +18284,7 @@ export interface paths { * * Example request for specific users: * ```bash - * curl --location 'http://0.0.0.0:4000/user/bulk_update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/user/bulk_update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "users": [ * { * "user_id": "user1", @@ -18302,7 +18302,7 @@ export interface paths { * * Example request for all users: * ```bash - * curl --location 'http://0.0.0.0:4000/user/bulk_update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/user/bulk_update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "all_users": true, * "user_updates": { * "user_role": "internal_user", @@ -18482,7 +18482,7 @@ export interface paths { * * ``` * curl --location 'http://0.0.0.0:4000/user/delete' - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * --header 'Content-Type: application/json' * --data-raw '{ * "user_ids": ["45e3e396-ee08-4a61-a88e-16b3ce7e0849"] @@ -18546,7 +18546,7 @@ export interface paths { * * Example request * ``` - * curl -X GET 'http://localhost:4000/user/info?user_id=krrish7%40berri.ai' --header 'Authorization: Bearer sk-1234' + * curl -X GET 'http://localhost:4000/user/info?user_id=krrish7%40berri.ai' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["user_info_user_info_get"]; @@ -18669,7 +18669,7 @@ export interface paths { * Usage Example * * ```shell - * curl -X POST "http://localhost:4000/user/new" -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST "http://localhost:4000/user/new" -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "username": "new_user", * "email": "new_user@example.com" * }' @@ -18753,7 +18753,7 @@ export interface paths { * @description Example curl * * ``` - * curl --location 'http://0.0.0.0:4000/user/update' --header 'Authorization: Bearer sk-1234' --header 'Content-Type: application/json' --data '{ + * curl --location 'http://0.0.0.0:4000/user/update' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --header 'Content-Type: application/json' --data '{ * "user_id": "test-litellm-user-4", * "user_role": "proxy_admin_viewer" * }' @@ -18845,7 +18845,7 @@ export interface paths { * * Example curl: * ``` - * curl -X GET --location 'http://localhost:4000/utils/model_info?model=gpt-4o&custom_llm_provider=openai' --header 'Authorization: Bearer sk-1234' + * curl -X GET --location 'http://localhost:4000/utils/model_info?model=gpt-4o&custom_llm_provider=openai' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["model_info_lookup_utils_model_info_get"]; @@ -18872,7 +18872,7 @@ export interface paths { * * Example curl: * ``` - * curl -X GET --location 'http://localhost:4000/utils/supported_openai_params?model=gpt-3.5-turbo-16k' --header 'Authorization: Bearer sk-1234' + * curl -X GET --location 'http://localhost:4000/utils/supported_openai_params?model=gpt-3.5-turbo-16k' --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["supported_openai_params_utils_supported_openai_params_get"]; @@ -19480,7 +19480,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches?limit=2 -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" + * curl http://localhost:4000/v1/batches?limit=2 -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" * ``` */ get: operations["list_batches_v1_batches_get"]; @@ -19493,7 +19493,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl http://localhost:4000/v1/batches -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "input_file_id": "file-abc123", * "endpoint": "/v1/chat/completions", * "completion_window": "24h" @@ -19522,7 +19522,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches/batch_abc123 -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" + * curl http://localhost:4000/v1/batches/batch_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" * ``` */ get: operations["retrieve_batch_v1_batches__batch_id__get"]; @@ -19552,7 +19552,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches/batch_abc123/cancel -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -X POST + * curl http://localhost:4000/v1/batches/batch_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -X POST * * ``` */ @@ -19579,7 +19579,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/chat/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-4o", * "messages": [ @@ -19614,7 +19614,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/completions * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "gpt-3.5-turbo-instruct", * "prompt": "Once upon a time", @@ -19646,12 +19646,12 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/containers?limit=20&order=desc" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/containers?limit=20&order=desc" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Or specify provider via header or query param: * ```bash - * curl -X GET "http://localhost:4000/v1/containers?custom_llm_provider=azure" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/containers?custom_llm_provider=azure" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["list_containers_v1_containers_get"]; @@ -19665,7 +19665,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "name": "My Container", * "expires_after": { * "anchor": "last_active_at", @@ -19676,7 +19676,7 @@ export interface paths { * * Or specify provider via header: * ```bash - * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer sk-1234" -H "custom-llm-provider: azure" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/containers" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "custom-llm-provider: azure" -H "Content-Type: application/json" -d '{ * "name": "My Container" * }' * ``` @@ -19704,12 +19704,12 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Or specify provider via header: * ```bash - * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" -H "custom-llm-provider: azure" + * curl -X GET "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "custom-llm-provider: azure" * ``` */ get: operations["retrieve_container_v1_containers__container_id__get"]; @@ -19724,12 +19724,12 @@ export interface paths { * * Example: * ```bash - * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" + * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Or specify provider via header: * ```bash - * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer sk-1234" -H "custom-llm-provider: azure" + * curl -X DELETE "http://localhost:4000/v1/containers/cntr_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "custom-llm-provider: azure" * ``` */ delete: operations["delete_container_v1_containers__container_id__delete"]; @@ -19824,7 +19824,7 @@ export interface paths { * ```bash * curl -X POST http://localhost:4000/v1/embeddings * -H "Content-Type: application/json" - * -H "Authorization: Bearer sk-1234" + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * -d '{ * "model": "text-embedding-ada-002", * "input": "The quick brown fox jumps over the lazy dog" @@ -20114,7 +20114,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -20129,7 +20129,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files -H "Authorization: Bearer sk-1234" -F purpose="batch" -F file="@mydata.jsonl" + * curl http://localhost:4000/v1/files -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F purpose="batch" -F file="@mydata.jsonl" * -F expires_after[anchor]="created_at" -F expires_after[seconds]=2592000 * ``` */ @@ -20156,7 +20156,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files/file-abc123 -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files/file-abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -20198,7 +20198,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files/file-abc123/content -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files/file-abc123/content -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -20239,7 +20239,7 @@ export interface paths { * * Example Curl: * ``` - * curl http://localhost:4000/v1/fine_tuning/jobs -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl http://localhost:4000/v1/fine_tuning/jobs -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-3.5-turbo", * "training_file": "file-abc123", * "hyperparameters": { @@ -20320,7 +20320,7 @@ export interface paths { * @description Follows the OpenAI Images API spec: https://platform.openai.com/docs/api-reference/images/create * * ```bash - * curl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST "http://localhost:4000/v1/images/edits" -H "Authorization: Bearer sk-1234" -F "model=gpt-image-1" -F "image[]=@soap.png" -F 'prompt=Create a studio ghibli image of this' + * curl -s -D >(grep -i x-request-id >&2) -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) -X POST "http://localhost:4000/v1/images/edits" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F "model=gpt-image-1" -F "image[]=@soap.png" -F 'prompt=Create a studio ghibli image of this' * ``` */ post: operations["image_edit_api_v1_images_edits_post"]; @@ -20359,7 +20359,7 @@ export interface paths { * @description List all vector store indexes. Proxy admin only. * * ```bash - * curl -L -X GET 'http://0.0.0.0:4000/v1/indexes' -H 'Authorization: Bearer sk-1234' + * curl -L -X GET 'http://0.0.0.0:4000/v1/indexes' -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["index_list_v1_indexes_get"]; @@ -20369,7 +20369,7 @@ export interface paths { * @description Create an index. Just writes the index to the database. * * ```bash - * curl -L -X POST 'http://0.0.0.0:4000/v1/indexes' -H 'Content-Type: application/json' -H 'Authorization: Bearer sk-1234' -d '{ + * curl -L -X POST 'http://0.0.0.0:4000/v1/indexes' -H 'Content-Type: application/json' -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "index_name": "dall-e-3", * "litellm_params": { * "vector_store_index": "real-index-name", @@ -21131,7 +21131,7 @@ export interface paths { * Example: * ```shell * curl -X GET 'http://localhost:4000/model/deprecations' \ - * -H 'Authorization: Bearer sk-1234' + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["model_deprecations_v1_model_deprecations_get"]; @@ -21298,7 +21298,7 @@ export interface paths { * @description The moderations endpoint is a tool you can use to check whether content complies with an LLM Providers policies. * Quick Start * ``` - * curl --location 'http://0.0.0.0:4000/moderations' --header 'Content-Type: application/json' --header 'Authorization: Bearer sk-1234' --data '{"input": "Sample text goes here", "model": "text-moderation-stable"}' + * curl --location 'http://0.0.0.0:4000/moderations' --header 'Content-Type: application/json' --header "Authorization: Bearer $LITELLM_MASTER_KEY" --data '{"input": "Sample text goes here", "model": "text-moderation-stable"}' * ``` */ post: operations["moderations_v1_moderations_post"]; @@ -21325,7 +21325,7 @@ export interface paths { * * **1. JSON body** (Mistral OCR API compatible): * ```bash - * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "model": "mistral-ocr", * "document": { * "type": "document_url", @@ -21336,7 +21336,7 @@ export interface paths { * * **2. Multipart form file upload**: * ```bash - * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer sk-1234" -F "model=mistral-ocr" -F "file=@document.pdf" + * curl -X POST "http://localhost:4000/v1/ocr" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F "model=mistral-ocr" -F "file=@document.pdf" * ``` * * Response format is normalized to the LiteLLM OCR schema by default. Providers @@ -21369,7 +21369,7 @@ export interface paths { * ## Form upload (for files): * ```bash * curl -X POST "http://localhost:4000/v1/rag/ingest" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -F file="@document.pdf" \ * -F 'ingest_options={"vector_store": {"custom_llm_provider": "openai"}}' * ``` @@ -21377,7 +21377,7 @@ export interface paths { * ## JSON body (for URLs): * ```bash * curl -X POST "http://localhost:4000/v1/rag/ingest" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H "Content-Type: application/json" \ * -d '{ * "file_url": "https://example.com/document.pdf", @@ -21388,7 +21388,7 @@ export interface paths { * ## Bedrock: * ```bash * curl -X POST "http://localhost:4000/v1/rag/ingest" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -F file="@document.pdf" \ * -F 'ingest_options={"vector_store": {"custom_llm_provider": "bedrock"}}' * ``` @@ -21422,7 +21422,7 @@ export interface paths { * ## Example Request: * ```bash * curl -X POST "http://localhost:4000/v1/rag/query" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H "Content-Type: application/json" \ * -d '{ * "model": "gpt-4o-mini", @@ -21438,7 +21438,7 @@ export interface paths { * ## With Reranking: * ```bash * curl -X POST "http://localhost:4000/v1/rag/query" \ - * -H "Authorization: Bearer sk-1234" \ + * -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ * -H "Content-Type: application/json" \ * -d '{ * "model": "gpt-4o-mini", @@ -21581,13 +21581,13 @@ export interface paths { * * ```bash * # Normal request - * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Tell me about AI" * }' * * # Background request with polling - * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Tell me about AI", * "background": true @@ -21619,7 +21619,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/compact * * ```bash - * curl -X POST http://localhost:4000/v1/responses/compact -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses/compact -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": [{"role": "user", "content": "Hello"}] * }' @@ -21648,7 +21648,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/input-tokens * * ```bash - * curl -X POST http://localhost:4000/v1/responses/input_tokens -H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" -d '{ + * curl -X POST http://localhost:4000/v1/responses/input_tokens -H "Content-Type: application/json" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d '{ * "model": "gpt-4o", * "input": "Hello, how are you?" * }' @@ -21682,10 +21682,10 @@ export interface paths { * * ```bash * # Get polling response - * curl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H "Authorization: Bearer sk-1234" + * curl -X GET http://localhost:4000/v1/responses/litellm_poll_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * # Get provider response - * curl -X GET http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer sk-1234" + * curl -X GET http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["get_response_v1_responses__response_id__get"]; @@ -21702,7 +21702,7 @@ export interface paths { * Follows the OpenAI Responses API spec: https://platform.openai.com/docs/api-reference/responses/delete * * ```bash - * curl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer sk-1234" + * curl -X DELETE http://localhost:4000/v1/responses/resp_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ delete: operations["delete_response_v1_responses__response_id__delete"]; @@ -21732,10 +21732,10 @@ export interface paths { * * ```bash * # Cancel polling response - * curl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H "Authorization: Bearer sk-1234" + * curl -X POST http://localhost:4000/v1/responses/litellm_poll_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * # Cancel provider response - * curl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H "Authorization: Bearer sk-1234" + * curl -X POST http://localhost:4000/v1/responses/resp_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ post: operations["cancel_response_v1_responses__response_id__cancel_post"]; @@ -21810,7 +21810,7 @@ export interface paths { * * Example with search_tool_name in URL (recommended - keeps body Perplexity-compatible): * ```bash - * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "query": "latest AI developments 2024", * "max_results": 5, * "search_domain_filter": ["arxiv.org", "nature.com"], @@ -21820,7 +21820,7 @@ export interface paths { * * Example with search_tool_name in body: * ```bash - * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "search_tool_name": "litellm-search", * "query": "latest AI developments 2024", * "max_results": 5, @@ -21883,7 +21883,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/search/tools" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/search/tools" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Response: @@ -21931,7 +21931,7 @@ export interface paths { * * Example with search_tool_name in URL (recommended - keeps body Perplexity-compatible): * ```bash - * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search/litellm-search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "query": "latest AI developments 2024", * "max_results": 5, * "search_domain_filter": ["arxiv.org", "nature.com"], @@ -21941,7 +21941,7 @@ export interface paths { * * Example with search_tool_name in body: * ```bash - * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/search" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "search_tool_name": "litellm-search", * "query": "latest AI developments 2024", * "max_results": 5, @@ -22750,7 +22750,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/videos" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["video_list_v1_videos_get"]; @@ -22764,7 +22764,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/videos" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "model": "sora-2", * "prompt": "A beautiful sunset over the ocean" * }' @@ -22795,7 +22795,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/characters" -H "Authorization: Bearer sk-1234" -F "video=@character_video.mp4" -F "name=my_character" + * curl -X POST "http://localhost:4000/v1/videos/characters" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F "video=@character_video.mp4" -F "name=my_character" * ``` */ post: operations["video_create_character_v1_videos_characters_post"]; @@ -22821,7 +22821,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos/characters/char_123" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/videos/characters/char_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["video_get_character_v1_videos_characters__character_id__get"]; @@ -22851,7 +22851,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/edits" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"prompt": "Make it brighter", "video": {"id": "video_123"}}' + * curl -X POST "http://localhost:4000/v1/videos/edits" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"prompt": "Make it brighter", "video": {"id": "video_123"}}' * ``` */ post: operations["video_edit_v1_videos_edits_post"]; @@ -22879,7 +22879,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/extensions" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"prompt": "Continue the scene", "seconds": "5", "video": {"id": "video_123"}}' + * curl -X POST "http://localhost:4000/v1/videos/extensions" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"prompt": "Continue the scene", "seconds": "5", "video": {"id": "video_123"}}' * ``` */ post: operations["video_extension_v1_videos_extensions_post"]; @@ -22905,7 +22905,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos/video_123" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/videos/video_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["video_status_v1_videos__video_id__get"]; @@ -22933,7 +22933,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos/{video_id}/content" -H "Authorization: Bearer sk-1234" --output video.mp4 + * curl -X GET "http://localhost:4000/v1/videos/{video_id}/content" -H "Authorization: Bearer $LITELLM_MASTER_KEY" --output video.mp4 * ``` */ get: operations["video_content_v1_videos__video_id__content_get"]; @@ -22963,7 +22963,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/video_123/remix" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/videos/video_123/remix" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "prompt": "A new version with different colors" * }' * ``` @@ -23230,7 +23230,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1beta/interactions" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1beta/interactions" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "model": "gemini/gemini-2.5-flash", * "input": "Hello, how are you?" * }' @@ -23429,7 +23429,7 @@ export interface paths { * * Example Curl: * ``` - * curl -X GET "http://0.0.0.0:4000/key/info" -H "Authorization: Bearer sk-1234" -d {"keys": ["sk-1", "sk-2", "sk-3"]} + * curl -X GET "http://0.0.0.0:4000/key/info" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -d {"keys": ["sk-1", "sk-2", "sk-3"]} * ``` */ post: operations["info_key_fn_v2_v2_key_info_post"]; @@ -23486,7 +23486,7 @@ export interface paths { * Example request: * ``` * curl -X GET 'http://localhost:4000/v2/model/info?include_team_models=true&page=1&size=50' \ - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` * * Example response: @@ -23635,7 +23635,7 @@ export interface paths { * Example request: * ``` * curl -X GET 'http://localhost:4000/v2/user/info?user_id=user123' \ - * --header 'Authorization: Bearer sk-1234' + * --header "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["user_info_v2_v2_user_info_get"]; @@ -24225,7 +24225,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/videos" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["video_list_videos_get"]; @@ -24239,7 +24239,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/videos" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "model": "sora-2", * "prompt": "A beautiful sunset over the ocean" * }' @@ -24270,7 +24270,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/characters" -H "Authorization: Bearer sk-1234" -F "video=@character_video.mp4" -F "name=my_character" + * curl -X POST "http://localhost:4000/v1/videos/characters" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F "video=@character_video.mp4" -F "name=my_character" * ``` */ post: operations["video_create_character_videos_characters_post"]; @@ -24296,7 +24296,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos/characters/char_123" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/videos/characters/char_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["video_get_character_videos_characters__character_id__get"]; @@ -24326,7 +24326,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/edits" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"prompt": "Make it brighter", "video": {"id": "video_123"}}' + * curl -X POST "http://localhost:4000/v1/videos/edits" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"prompt": "Make it brighter", "video": {"id": "video_123"}}' * ``` */ post: operations["video_edit_videos_edits_post"]; @@ -24354,7 +24354,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/extensions" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"prompt": "Continue the scene", "seconds": "5", "video": {"id": "video_123"}}' + * curl -X POST "http://localhost:4000/v1/videos/extensions" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{"prompt": "Continue the scene", "seconds": "5", "video": {"id": "video_123"}}' * ``` */ post: operations["video_extension_videos_extensions_post"]; @@ -24380,7 +24380,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos/video_123" -H "Authorization: Bearer sk-1234" + * curl -X GET "http://localhost:4000/v1/videos/video_123" -H "Authorization: Bearer $LITELLM_MASTER_KEY" * ``` */ get: operations["video_status_videos__video_id__get"]; @@ -24408,7 +24408,7 @@ export interface paths { * * Example: * ```bash - * curl -X GET "http://localhost:4000/v1/videos/{video_id}/content" -H "Authorization: Bearer sk-1234" --output video.mp4 + * curl -X GET "http://localhost:4000/v1/videos/{video_id}/content" -H "Authorization: Bearer $LITELLM_MASTER_KEY" --output video.mp4 * ``` */ get: operations["video_content_videos__video_id__content_get"]; @@ -24438,7 +24438,7 @@ export interface paths { * * Example: * ```bash - * curl -X POST "http://localhost:4000/v1/videos/video_123/remix" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl -X POST "http://localhost:4000/v1/videos/video_123/remix" -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "prompt": "A new version with different colors" * }' * ``` @@ -24708,7 +24708,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches?limit=2 -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" + * curl http://localhost:4000/v1/batches?limit=2 -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" * ``` */ get: operations["list_batches__provider__v1_batches_get"]; @@ -24721,7 +24721,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{ + * curl http://localhost:4000/v1/batches -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -d '{ * "input_file_id": "file-abc123", * "endpoint": "/v1/chat/completions", * "completion_window": "24h" @@ -24750,7 +24750,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches/batch_abc123 -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" + * curl http://localhost:4000/v1/batches/batch_abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" * ``` */ get: operations["retrieve_batch__provider__v1_batches__batch_id__get"]; @@ -24780,7 +24780,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/batches/batch_abc123/cancel -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -X POST + * curl http://localhost:4000/v1/batches/batch_abc123/cancel -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" -X POST * * ``` */ @@ -24807,7 +24807,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -24822,7 +24822,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files -H "Authorization: Bearer sk-1234" -F purpose="batch" -F file="@mydata.jsonl" + * curl http://localhost:4000/v1/files -H "Authorization: Bearer $LITELLM_MASTER_KEY" -F purpose="batch" -F file="@mydata.jsonl" * -F expires_after[anchor]="created_at" -F expires_after[seconds]=2592000 * ``` */ @@ -24849,7 +24849,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files/file-abc123 -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files/file-abc123 -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */ @@ -24891,7 +24891,7 @@ export interface paths { * * Example Curl * ``` - * curl http://localhost:4000/v1/files/file-abc123/content -H "Authorization: Bearer sk-1234" + * curl http://localhost:4000/v1/files/file-abc123/content -H "Authorization: Bearer $LITELLM_MASTER_KEY" * * ``` */