sdk-core icon indicating copy to clipboard operation
sdk-core copied to clipboard

[Bug] TLS error message & documentation for API key auth

Open pearkes opened this issue 11 months ago • 3 comments

If you're using Temporal Cloud with API key authentication for a namespace:

$ tcld namespace auth-method get -namespace quickstart-jack.xxxxx
api_key

And connecting with Python:

TASK_QUEUE = os.environ.get("TASK_QUEUE", "tasks")
TEMPORAL_ADDRESS = os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")
TEMPORAL_NAMESPACE = os.environ.get("TEMPORAL_NAMESPACE", "default")
TEMPORAL_API_KEY = os.environ.get("TEMPORAL_API_KEY", "")

async def main() -> None:
    client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE, api_key=TEMPORAL_API_KEY)
    executor = ThreadPoolExecutor()
    worker = Worker(
        client,
        task_queue=TASK_QUEUE,
        workflows=load_workflows(),
        activities=load_activities(),
        activity_executor=executor,
    )
    await worker.run()

This will raise this error:

$ poetry run python worker.py
Traceback (most recent call last):
  File "/Users/pearkes/code/jack/temporal/worker.py", line 75, in <module>
    asyncio.run(main())
    ~~~~~~~~~~~^^^^^^^^
  File "/Users/pearkes/.local/share/uv/python/cpython-3.13.2-macos-aarch64-none/lib/python3.13/asyncio/runners.py", line 195, in run
    return runner.run(main)
           ~~~~~~~~~~^^^^^^
  File "/Users/pearkes/.local/share/uv/python/cpython-3.13.2-macos-aarch64-none/lib/python3.13/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/Users/pearkes/.local/share/uv/python/cpython-3.13.2-macos-aarch64-none/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/Users/pearkes/code/jack/temporal/worker.py", line 62, in main
    client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE, api_key=TEMPORAL_API_KEY)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/client.py", line 177, in connect
    await temporalio.service.ServiceClient.connect(connect_config),                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/service.py", line 209, in connect
    return await _BridgeServiceClient.connect(config)                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                       File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/service.py", line 1212, in connect                                                                            await client._connected_client()
  File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/service.py", line 1225, in _connected_client                                                                  self._bridge_client = await temporalio.bridge.client.Client.connect(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<2 lines>...                                                                                           )                                                                                                         ^
  File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/bridge/client.py", line 97, in connect                                                                        await temporalio.bridge.temporal_sdk_bridge.connect_client(                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        runtime._ref, config                                                                                      ^^^^^^^^^^^^^^^^^^^^
    ),                                                                                                        ^
RuntimeError: Failed client connect: `get_system_info` call error after connection: Status { code: Unknown, message: "transport error", source: Some(tonic::transport::Error(Transport, hyper::Error(Io, Kind(ConnectionReset)))) }
  1. Status { code: Unknown, message: "transport error" ... is quite inscrutable and could be considerably improved.
  2. You need to set TLS to True – this wasn't clear in the getting started docs, nor were API keys as an auth method mentioned. I found a reference to it in the Python client docs and figured that may be it.

This works:

TASK_QUEUE = os.environ.get("TASK_QUEUE", "tasks")
TEMPORAL_ADDRESS = os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")
TEMPORAL_NAMESPACE = os.environ.get("TEMPORAL_NAMESPACE", "default")
TEMPORAL_API_KEY = os.environ.get("TEMPORAL_API_KEY", "")
TEMPORAL_TLS = bool(os.environ.get("TEMPORAL_TLS", False))

async def main() -> None:
    client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE, api_key=TEMPORAL_API_KEY, tls=TEMPORAL_TLS)
    # Use a thread pool executor for synchronous activities
    executor = ThreadPoolExecutor()
    worker = Worker(
        client,
        task_queue=TASK_QUEUE,
        workflows=load_workflows(),
        activities=load_activities(),
        activity_executor=executor,
    )
    await worker.run()

pearkes avatar Jun 01 '25 13:06 pearkes

Status { code: Unknown, message: "transport error" ... is quite inscrutable and could be considerably improved.

For security reasons, often attempting to connect to TLS endpoint without TLS doesn't give too many details. This is reported by our Rust extension when the connection fails. We may be able to improve some of the phrasing if "transport error" is unclear, but it'll still be a basic "reset".

this wasn't clear in the getting started docs, nor were API keys as an auth method mentioned

The API key methods and the TLS settings are currently being improved by our docs team (in https://github.com/temporalio/documentation)

cretz avatar Jun 02 '25 13:06 cretz

Cool, thanks. Maybe a client side description of the error that points to further documentation, or similar? Understood it's a pretty generic error.

pearkes avatar Jun 02 '25 15:06 pearkes

Transferring to sdk-core where the error message originates...

cretz avatar Jun 03 '25 16:06 cretz