Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions temporalio/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ async def connect(
default_workflow_query_reject_condition: Optional[
temporalio.common.QueryRejectCondition
] = None,
tls: Union[bool, TLSConfig] = False,
tls: Union[bool, TLSConfig, None] = None,
retry_config: Optional[RetryConfig] = None,
keep_alive_config: Optional[KeepAliveConfig] = KeepAliveConfig.default,
rpc_metadata: Mapping[str, Union[str, bytes]] = {},
Expand Down Expand Up @@ -166,9 +166,11 @@ async def connect(
condition for workflow queries if not set during query. See
:py:meth:`WorkflowHandle.query` for details on the rejection
condition.
tls: If false, the default, do not use TLS. If true, use system
default TLS configuration. If TLS configuration present, that
TLS configuration will be used.
tls: If ``None``, the default, TLS will be enabled automatically
when ``api_key`` is provided, otherwise TLS is disabled. If
``False``, do not use TLS. If ``True``, use system default TLS
configuration. If TLS configuration present, that TLS
configuration will be used.
retry_config: Retry configuration for direct service calls (when
opted in) or all high-level calls made by this client (which all
opt-in to retries by default). If unset, a default retry
Expand Down
6 changes: 5 additions & 1 deletion temporalio/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class ConnectConfig:

target_host: str
api_key: Optional[str] = None
tls: Union[bool, TLSConfig] = False
tls: Union[bool, TLSConfig, None] = None
retry_config: Optional[RetryConfig] = None
keep_alive_config: Optional[KeepAliveConfig] = KeepAliveConfig.default
rpc_metadata: Mapping[str, Union[str, bytes]] = field(default_factory=dict)
Expand Down Expand Up @@ -172,6 +172,10 @@ def _to_bridge_config(self) -> temporalio.bridge.client.ClientConfig:
elif self.tls:
target_url = f"https://{self.target_host}"
tls_config = TLSConfig()._to_bridge_config()
# Enable TLS by default when API key is provided and tls not explicitly set
elif self.tls is None and self.api_key is not None:
target_url = f"https://{self.target_host}"
tls_config = TLSConfig()._to_bridge_config()
else:
target_url = f"http://{self.target_host}"
tls_config = None
Expand Down
1 change: 1 addition & 0 deletions tests/api/test_grpc_stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ async def test_grpc_metadata():
f"localhost:{port}",
api_key="my-api-key",
rpc_metadata={"my-meta-key": "my-meta-val"},
tls=False,
)
workflow_server.assert_last_metadata(
{
Expand Down
2 changes: 1 addition & 1 deletion tests/test_envconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ async def test_e2e_multi_profile_different_client_connections(client: Client):
assert dev_client.service_client.config.target_host == target_host
assert dev_client.namespace == "dev"
assert dev_client.service_client.config.api_key is None
assert dev_client.service_client.config.tls is False
assert dev_client.service_client.config.tls is None

assert prod_client.service_client.config.target_host == target_host
assert prod_client.namespace == "prod"
Expand Down
1 change: 1 addition & 0 deletions tests/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ async def connect_service_client(
next: Callable[[ConnectConfig], Awaitable[ServiceClient]],
) -> ServiceClient:
config.api_key = "replaced key"
config.tls = False
return await next(config)


Expand Down
49 changes: 49 additions & 0 deletions tests/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,55 @@ async def test_grpc_status(client: Client, env: WorkflowEnvironment):
)


def test_connect_config_tls_enabled_by_default_when_api_key_provided():
"""Test that TLS is enabled by default when API key is provided and tls is not configured."""
config = temporalio.service.ConnectConfig(
target_host="localhost:7233",
api_key="test-api-key",
)
# TLS should be auto-enabled when api_key is provided and tls not explicitly set
bridge_config = config._to_bridge_config()
assert bridge_config.target_url == "https://localhost:7233"
assert bridge_config.tls_config is not None


def test_connect_config_tls_can_be_explicitly_disabled_even_when_api_key_provided():
"""Test that TLS can be explicitly disabled even when API key is provided."""
config = temporalio.service.ConnectConfig(
target_host="localhost:7233",
api_key="test-api-key",
tls=False,
)
# TLS should remain disabled when explicitly set to False
assert config.tls is False


def test_connect_config_tls_disabled_by_default_when_no_api_key():
"""Test that TLS is disabled by default when no API key is provided."""
config = temporalio.service.ConnectConfig(
target_host="localhost:7233",
)
# TLS should remain disabled when no api_key is provided
bridge_config = config._to_bridge_config()
assert bridge_config.target_url == "http://localhost:7233"
assert bridge_config.tls_config is None


def test_connect_config_tls_explicit_config_preserved():
"""Test that explicit TLS configuration is preserved regardless of API key."""
tls_config = temporalio.service.TLSConfig(
server_root_ca_cert=b"test-cert",
domain="test-domain",
)
config = temporalio.service.ConnectConfig(
target_host="localhost:7233",
api_key="test-api-key",
tls=tls_config,
)
# Explicit TLS config should be preserved
assert config.tls == tls_config


async def test_rpc_execution_not_unknown(client: Client):
"""
Execute each rpc method and expect a failure, but ensure the failure is not that the rpc method is unknown
Expand Down
Loading