From a983b2dab8aad2ba07ee8540b079043392be9205 Mon Sep 17 00:00:00 2001 From: Brian Newsom Date: Thu, 6 Aug 2026 23:08:47 -0600 Subject: [PATCH 1/2] fix(cli): persist Anthropic auth header format Signed-off-by: Brian Newsom --- .../nemo_platform_ext/cli/commands/setup.py | 9 ++-- .../tests/cli/commands/test_setup.py | 45 ++++++++++++++----- .../src/nemo_platform/cli/commands/setup.py | 9 ++-- .../cli/commands/test_setup.py | 45 ++++++++++++++----- 4 files changed, 78 insertions(+), 30 deletions(-) diff --git a/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py b/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py index 0f01055aee..8aa8a0e63b 100644 --- a/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py +++ b/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py @@ -542,9 +542,7 @@ def _create_provider( if secret_name: kwargs["api_key_secret_name"] = secret_name if auth_header_format: - header_name, _, header_value = auth_header_format.partition(":") - if header_name and header_value: - kwargs["required_extra_headers"] = {header_name.strip(): header_value.strip()} + kwargs["auth_header_format"] = auth_header_format if default_extra_headers: kwargs["default_extra_headers"] = default_extra_headers provider_type = _provider_type_for_connection(name, host_url) @@ -571,6 +569,7 @@ def _update_provider( host_url: str, secret_name: str | None, workspace: str, + auth_header_format: str | None = None, default_extra_headers: dict[str, str] | None = None, ) -> None: kwargs: dict = { @@ -579,6 +578,8 @@ def _update_provider( } if secret_name: kwargs["api_key_secret_name"] = secret_name + if auth_header_format: + kwargs["auth_header_format"] = auth_header_format if default_extra_headers: kwargs["default_extra_headers"] = default_extra_headers provider_type = _provider_type_for_connection(name, host_url) @@ -1734,6 +1735,7 @@ def _register_provider_interactive( host_url=host_url, secret_name=secret_name, workspace=workspace, + auth_header_format=auth_header_format, default_extra_headers=default_extra_headers, ) console.print(f" {CHECK} Updated provider '{provider_name}' ({host_url})") @@ -1904,6 +1906,7 @@ def _auto_setup(client: NeMoPlatform, workspace: str) -> bool: host_url=host_url, secret_name=secret_name, workspace=workspace, + auth_header_format=auth_header_format, default_extra_headers=default_extra_headers, ) console.print(f" {CHECK} Updated provider '{provider_name}' ({host_url})") diff --git a/packages/nemo_platform_ext/tests/cli/commands/test_setup.py b/packages/nemo_platform_ext/tests/cli/commands/test_setup.py index 61359c8325..3579595e39 100644 --- a/packages/nemo_platform_ext/tests/cli/commands/test_setup.py +++ b/packages/nemo_platform_ext/tests/cli/commands/test_setup.py @@ -391,7 +391,7 @@ def _make_client(self): return client def test_anthropic_provider_kwargs(self): - """auth_header_format must be mapped to required_extra_headers, not passed raw.""" + """Provider creation keeps auth templating in the dedicated field.""" client = self._make_client() _create_provider( client, @@ -403,12 +403,13 @@ def test_anthropic_provider_kwargs(self): default_extra_headers={"anthropic-version": "2023-06-01"}, ) call_kwargs = client.inference.providers.create.call_args.kwargs - assert "auth_header_format" not in call_kwargs - assert call_kwargs["required_extra_headers"]["X-Api-Key"] == "{{ auth_secret }}" + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs assert call_kwargs["default_extra_headers"] == {"anthropic-version": "2023-06-01"} - def test_no_auth_header_format_skips_required_extra_headers(self): - """When auth_header_format is None, required_extra_headers should not be added.""" + def test_no_auth_header_format_skips_auth_fields(self): + """Providers using default Bearer auth do not send auth overrides.""" client = self._make_client() _create_provider( client, @@ -526,15 +527,18 @@ def test_priority_order(self): assert create_kwargs.kwargs["name"] == "anthropic" def test_anthropic_auto_setup_maps_auth_header(self): - """Auto-setup with ANTHROPIC_API_KEY must map auth_header_format to required_extra_headers.""" + """Auto-setup persists the Anthropic auth template without exposing the key.""" client = _make_mock_client() - with patch.dict("os.environ", {"ANTHROPIC_API_KEY": "sk-ant-test"}, clear=True): + api_key = "sk-ant-test" + with patch.dict("os.environ", {"ANTHROPIC_API_KEY": api_key}, clear=True): result = _auto_setup(client, "default") assert result is True call_kwargs = client.inference.providers.create.call_args.kwargs assert call_kwargs["name"] == "anthropic" - assert "auth_header_format" not in call_kwargs - assert "X-Api-Key" in call_kwargs["required_extra_headers"] + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs + assert api_key not in str(call_kwargs) # --------------------------------------------------------------------------- @@ -1690,21 +1694,38 @@ def test_fresh_install_creates_both(self): client.inference.providers.update.assert_not_called() def test_existing_provider_updated_with_extra_headers(self): - """Provider update passes through default_extra_headers (auth_header_format is create-only).""" + """Provider update repairs Anthropic auth without exposing the API key.""" client = _make_mock_client(secret_exists=False, provider_exists=True) + api_key = "sk-ant-test" _register_provider_interactive( client, provider_name="anthropic", host_url="https://api.anthropic.com", - api_key="sk-ant-test", + api_key=api_key, workspace="default", auth_header_format="X-Api-Key: {{ auth_secret }}", default_extra_headers={"anthropic-version": "2023-06-01"}, ) call_kwargs = client.inference.providers.update.call_args.kwargs - assert "auth_header_format" not in call_kwargs + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs + assert api_key not in str(call_kwargs) assert call_kwargs["default_extra_headers"] == {"anthropic-version": "2023-06-01"} + def test_auto_setup_updates_existing_anthropic_auth(self): + """Auto setup repairs an existing Anthropic provider's auth template.""" + client = _make_mock_client(provider_exists=True, secret_exists=True) + api_key = "sk-ant-updated" + with patch.dict("os.environ", {"ANTHROPIC_API_KEY": api_key}, clear=True): + result = _auto_setup(client, "default") + assert result is True + call_kwargs = client.inference.providers.update.call_args.kwargs + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs + assert api_key not in str(call_kwargs) + # -- auto path -- def test_auto_setup_updates_existing_provider_secret_binding(self): diff --git a/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py b/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py index 598e681a08..2a8fd6d871 100644 --- a/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py +++ b/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py @@ -542,9 +542,7 @@ def _create_provider( if secret_name: kwargs["api_key_secret_name"] = secret_name if auth_header_format: - header_name, _, header_value = auth_header_format.partition(":") - if header_name and header_value: - kwargs["required_extra_headers"] = {header_name.strip(): header_value.strip()} + kwargs["auth_header_format"] = auth_header_format if default_extra_headers: kwargs["default_extra_headers"] = default_extra_headers provider_type = _provider_type_for_connection(name, host_url) @@ -571,6 +569,7 @@ def _update_provider( host_url: str, secret_name: str | None, workspace: str, + auth_header_format: str | None = None, default_extra_headers: dict[str, str] | None = None, ) -> None: kwargs: dict = { @@ -579,6 +578,8 @@ def _update_provider( } if secret_name: kwargs["api_key_secret_name"] = secret_name + if auth_header_format: + kwargs["auth_header_format"] = auth_header_format if default_extra_headers: kwargs["default_extra_headers"] = default_extra_headers provider_type = _provider_type_for_connection(name, host_url) @@ -1734,6 +1735,7 @@ def _register_provider_interactive( host_url=host_url, secret_name=secret_name, workspace=workspace, + auth_header_format=auth_header_format, default_extra_headers=default_extra_headers, ) console.print(f" {CHECK} Updated provider '{provider_name}' ({host_url})") @@ -1904,6 +1906,7 @@ def _auto_setup(client: NeMoPlatform, workspace: str) -> bool: host_url=host_url, secret_name=secret_name, workspace=workspace, + auth_header_format=auth_header_format, default_extra_headers=default_extra_headers, ) console.print(f" {CHECK} Updated provider '{provider_name}' ({host_url})") diff --git a/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py b/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py index 6eb6d36555..1acb7b13ea 100644 --- a/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py +++ b/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py @@ -391,7 +391,7 @@ def _make_client(self): return client def test_anthropic_provider_kwargs(self): - """auth_header_format must be mapped to required_extra_headers, not passed raw.""" + """Provider creation keeps auth templating in the dedicated field.""" client = self._make_client() _create_provider( client, @@ -403,12 +403,13 @@ def test_anthropic_provider_kwargs(self): default_extra_headers={"anthropic-version": "2023-06-01"}, ) call_kwargs = client.inference.providers.create.call_args.kwargs - assert "auth_header_format" not in call_kwargs - assert call_kwargs["required_extra_headers"]["X-Api-Key"] == "{{ auth_secret }}" + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs assert call_kwargs["default_extra_headers"] == {"anthropic-version": "2023-06-01"} - def test_no_auth_header_format_skips_required_extra_headers(self): - """When auth_header_format is None, required_extra_headers should not be added.""" + def test_no_auth_header_format_skips_auth_fields(self): + """Providers using default Bearer auth do not send auth overrides.""" client = self._make_client() _create_provider( client, @@ -526,15 +527,18 @@ def test_priority_order(self): assert create_kwargs.kwargs["name"] == "anthropic" def test_anthropic_auto_setup_maps_auth_header(self): - """Auto-setup with ANTHROPIC_API_KEY must map auth_header_format to required_extra_headers.""" + """Auto-setup persists the Anthropic auth template without exposing the key.""" client = _make_mock_client() - with patch.dict("os.environ", {"ANTHROPIC_API_KEY": "sk-ant-test"}, clear=True): + api_key = "sk-ant-test" + with patch.dict("os.environ", {"ANTHROPIC_API_KEY": api_key}, clear=True): result = _auto_setup(client, "default") assert result is True call_kwargs = client.inference.providers.create.call_args.kwargs assert call_kwargs["name"] == "anthropic" - assert "auth_header_format" not in call_kwargs - assert "X-Api-Key" in call_kwargs["required_extra_headers"] + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs + assert api_key not in str(call_kwargs) # --------------------------------------------------------------------------- @@ -1690,21 +1694,38 @@ def test_fresh_install_creates_both(self): client.inference.providers.update.assert_not_called() def test_existing_provider_updated_with_extra_headers(self): - """Provider update passes through default_extra_headers (auth_header_format is create-only).""" + """Provider update repairs Anthropic auth without exposing the API key.""" client = _make_mock_client(secret_exists=False, provider_exists=True) + api_key = "sk-ant-test" _register_provider_interactive( client, provider_name="anthropic", host_url="https://api.anthropic.com", - api_key="sk-ant-test", + api_key=api_key, workspace="default", auth_header_format="X-Api-Key: {{ auth_secret }}", default_extra_headers={"anthropic-version": "2023-06-01"}, ) call_kwargs = client.inference.providers.update.call_args.kwargs - assert "auth_header_format" not in call_kwargs + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs + assert api_key not in str(call_kwargs) assert call_kwargs["default_extra_headers"] == {"anthropic-version": "2023-06-01"} + def test_auto_setup_updates_existing_anthropic_auth(self): + """Auto setup repairs an existing Anthropic provider's auth template.""" + client = _make_mock_client(provider_exists=True, secret_exists=True) + api_key = "sk-ant-updated" + with patch.dict("os.environ", {"ANTHROPIC_API_KEY": api_key}, clear=True): + result = _auto_setup(client, "default") + assert result is True + call_kwargs = client.inference.providers.update.call_args.kwargs + assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" + assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" + assert "required_extra_headers" not in call_kwargs + assert api_key not in str(call_kwargs) + # -- auto path -- def test_auto_setup_updates_existing_provider_secret_binding(self): From 242b66df170662843abfb93e7e9b0714f027dcd9 Mon Sep 17 00:00:00 2001 From: Brian Newsom Date: Fri, 7 Aug 2026 09:28:20 -0600 Subject: [PATCH 2/2] fix(cli): explicitly clear legacy Anthropic auth headers Signed-off-by: Brian Newsom --- .../src/nemo_platform_ext/cli/commands/setup.py | 1 + packages/nemo_platform_ext/tests/cli/commands/test_setup.py | 4 ++-- .../nemo-platform/src/nemo_platform/cli/commands/setup.py | 1 + .../vendored/nemo_platform_ext/cli/commands/test_setup.py | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py b/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py index 8aa8a0e63b..e6c3f2bbd3 100644 --- a/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py +++ b/packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/setup.py @@ -580,6 +580,7 @@ def _update_provider( kwargs["api_key_secret_name"] = secret_name if auth_header_format: kwargs["auth_header_format"] = auth_header_format + kwargs["required_extra_headers"] = None if default_extra_headers: kwargs["default_extra_headers"] = default_extra_headers provider_type = _provider_type_for_connection(name, host_url) diff --git a/packages/nemo_platform_ext/tests/cli/commands/test_setup.py b/packages/nemo_platform_ext/tests/cli/commands/test_setup.py index 3579595e39..0c2ec42a6f 100644 --- a/packages/nemo_platform_ext/tests/cli/commands/test_setup.py +++ b/packages/nemo_platform_ext/tests/cli/commands/test_setup.py @@ -1709,7 +1709,7 @@ def test_existing_provider_updated_with_extra_headers(self): call_kwargs = client.inference.providers.update.call_args.kwargs assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" - assert "required_extra_headers" not in call_kwargs + assert call_kwargs["required_extra_headers"] is None assert api_key not in str(call_kwargs) assert call_kwargs["default_extra_headers"] == {"anthropic-version": "2023-06-01"} @@ -1723,7 +1723,7 @@ def test_auto_setup_updates_existing_anthropic_auth(self): call_kwargs = client.inference.providers.update.call_args.kwargs assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" - assert "required_extra_headers" not in call_kwargs + assert call_kwargs["required_extra_headers"] is None assert api_key not in str(call_kwargs) # -- auto path -- diff --git a/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py b/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py index 2a8fd6d871..8883b93a00 100644 --- a/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py +++ b/sdk/python/nemo-platform/src/nemo_platform/cli/commands/setup.py @@ -580,6 +580,7 @@ def _update_provider( kwargs["api_key_secret_name"] = secret_name if auth_header_format: kwargs["auth_header_format"] = auth_header_format + kwargs["required_extra_headers"] = None if default_extra_headers: kwargs["default_extra_headers"] = default_extra_headers provider_type = _provider_type_for_connection(name, host_url) diff --git a/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py b/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py index 1acb7b13ea..d237db00cf 100644 --- a/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py +++ b/sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_setup.py @@ -1709,7 +1709,7 @@ def test_existing_provider_updated_with_extra_headers(self): call_kwargs = client.inference.providers.update.call_args.kwargs assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" - assert "required_extra_headers" not in call_kwargs + assert call_kwargs["required_extra_headers"] is None assert api_key not in str(call_kwargs) assert call_kwargs["default_extra_headers"] == {"anthropic-version": "2023-06-01"} @@ -1723,7 +1723,7 @@ def test_auto_setup_updates_existing_anthropic_auth(self): call_kwargs = client.inference.providers.update.call_args.kwargs assert call_kwargs["api_key_secret_name"] == "anthropic-api-key" assert call_kwargs["auth_header_format"] == "X-Api-Key: {{ auth_secret }}" - assert "required_extra_headers" not in call_kwargs + assert call_kwargs["required_extra_headers"] is None assert api_key not in str(call_kwargs) # -- auto path --