From 1b854bc74def2052eb66af57124e3d8d1a0ff74f Mon Sep 17 00:00:00 2001 From: uartnet <140632163+uartnet@users.noreply.github.com> Date: Fri, 9 Oct 2026 13:20:38 +0200 Subject: [PATCH] test(config): cover unsupported external mTLS signers --- docs/001-configuration.md | 8 ++++++- tests/unit/test_config.py | 49 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/docs/001-configuration.md b/docs/001-configuration.md index 3b1d0f8..6b78998 100644 --- a/docs/001-configuration.md +++ b/docs/001-configuration.md @@ -84,4 +84,10 @@ transport or credential storage settings instead of ignoring them: - Datagram tunnels. - SOCKS or custom proxy transport. - Custom DNS transport settings. -- Keychain, PKCS#11, or other external credential stores. +- Keychain, PKCS#11, external mTLS signers (`auth.mtls.storage.kind: exec`), + or other external credential stores. + +The `exec` backend is supported by the Go SDK and CLI. Selecting a context or +environment that uses it raises `ERR_RSTREAM_UNSUPPORTED_MTLS_STORAGE` before +connecting; this SDK never executes the configured helper. Other contexts in the +same configuration file remain usable. diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index 6f5120c..2d1ff08 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -15,6 +15,55 @@ from rstream.errors import ConfigurationError, UnsupportedFeatureError +@pytest.mark.parametrize("environment", [False, True]) +def test_external_mtls_signer_is_explicitly_unsupported( + tmp_path: Path, environment: bool +) -> None: + config = tmp_path / "config.yaml" + config.write_text( + ( + "environments:\n - apiUrl: https://rstream.io\n" + if environment + else "contexts:\n - name: external\n engine: engine.example:443\n" + ) + + """ auth: + mtls: + storage: + kind: exec + certificateSHA256: >- + 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef + exec: + command: /nonexistent/identity-helper + args: [--slot, device] +""" + + ( + "contexts:\n - name: external\n apiUrl: https://rstream.io\n" + " engine: engine.example:443\n" + if environment + else "" + ) + + " - name: software\n apiUrl: https://other.example\n" + " engine: software.example:443\n", + encoding="utf-8", + ) + with pytest.raises(UnsupportedFeatureError) as failure: + asyncio.run( + resolve_client_options( + ClientOptions(config_path=str(config), context="external") + ) + ) + assert failure.value.code == "ERR_RSTREAM_UNSUPPORTED_MTLS_STORAGE" + assert str(failure.value) == ( + "mTLS storage provider 'exec' is not supported by rstream-python." + ) + resolved = asyncio.run( + resolve_client_options( + ClientOptions(config_path=str(config), context="software", no_token=True) + ) + ) + assert resolved.engine == "software.example:443" + + def test_default_runtime_timeouts_are_resolved() -> None: resolved = asyncio.run( resolve_client_options(ClientOptions(read_config_file=False, no_token=True))