From 60f976950cbafc8527ce7673edb6804a0a4bfe67 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Tue, 2 Dec 2025 09:17:40 -0800 Subject: [PATCH 1/4] enable TLS if api key provided --- temporalio/lib/temporalio/client.rb | 2 +- .../lib/temporalio/client/connection.rb | 5 +- temporalio/test/client_connection_test.rb | 60 +++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 temporalio/test/client_connection_test.rb diff --git a/temporalio/lib/temporalio/client.rb b/temporalio/lib/temporalio/client.rb index b60f3c6e..54694233 100644 --- a/temporalio/lib/temporalio/client.rb +++ b/temporalio/lib/temporalio/client.rb @@ -99,7 +99,7 @@ def self.connect( target_host, namespace, api_key: nil, - tls: false, + tls: nil, data_converter: Converters::DataConverter.default, interceptors: [], logger: Logger.new($stdout, level: Logger::WARN), diff --git a/temporalio/lib/temporalio/client/connection.rb b/temporalio/lib/temporalio/client/connection.rb index 2199e52e..422452c1 100644 --- a/temporalio/lib/temporalio/client/connection.rb +++ b/temporalio/lib/temporalio/client/connection.rb @@ -173,7 +173,7 @@ class HTTPConnectProxyOptions; end # rubocop:disable Lint/EmptyClass def initialize( target_host:, api_key: nil, - tls: false, + tls: nil, rpc_metadata: {}, rpc_retry: RPCRetryOptions.new, identity: "#{Process.pid}@#{Socket.gethostname}", @@ -182,6 +182,9 @@ def initialize( runtime: Runtime.default, lazy_connect: false ) + # Auto-enable TLS when API key provided and tls not explicitly set + tls = true if tls.nil? && !api_key.nil? + @options = Options.new( target_host:, api_key:, diff --git a/temporalio/test/client_connection_test.rb b/temporalio/test/client_connection_test.rb new file mode 100644 index 00000000..0aa4833c --- /dev/null +++ b/temporalio/test/client_connection_test.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'temporalio/client/connection' +require 'test' + +class ClientConnectionTest < Test + def test_connection_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 + connection = Temporalio::Client::Connection.new( + target_host: 'localhost:7233', + api_key: 'test-api-key', + lazy_connect: true + ) + + # TLS should be auto-enabled when api_key is provided and tls not explicitly set + assert_equal true, connection.options.tls + end + + def test_connection_tls_can_be_explicitly_disabled_with_api_key + # Test that TLS can be explicitly disabled even when API key is provided + connection = Temporalio::Client::Connection.new( + target_host: 'localhost:7233', + api_key: 'test-api-key', + tls: false, + lazy_connect: true + ) + + # TLS should remain disabled when explicitly set to false + assert_equal false, connection.options.tls + end + + def test_connection_tls_disabled_by_default_without_api_key + # Test that TLS is disabled by default when no API key is provided + connection = Temporalio::Client::Connection.new( + target_host: 'localhost:7233', + lazy_connect: true + ) + + # TLS should remain nil (falsy) when no api_key is provided + refute connection.options.tls + end + + def test_connection_explicit_tls_config_preserved_with_api_key + # Test that explicit TLS configuration is preserved regardless of API key + tls_options = Temporalio::Client::Connection::TLSOptions.new( + server_root_ca_cert: 'test-cert', + domain: 'test-domain' + ) + + connection = Temporalio::Client::Connection.new( + target_host: 'localhost:7233', + api_key: 'test-api-key', + tls: tls_options, + lazy_connect: true + ) + + # Explicit TLS config should be preserved + assert_equal tls_options, connection.options.tls + end +end From a1a4a610a24d7fb7da039feb474a7ed74a0c6297 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Tue, 2 Dec 2025 09:43:10 -0800 Subject: [PATCH 2/4] fix --- temporalio/lib/temporalio/client/connection.rb | 3 ++- temporalio/test/client_connection_test.rb | 11 ----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/temporalio/lib/temporalio/client/connection.rb b/temporalio/lib/temporalio/client/connection.rb index 422452c1..8a565bb4 100644 --- a/temporalio/lib/temporalio/client/connection.rb +++ b/temporalio/lib/temporalio/client/connection.rb @@ -183,7 +183,8 @@ def initialize( lazy_connect: false ) # Auto-enable TLS when API key provided and tls not explicitly set - tls = true if tls.nil? && !api_key.nil? + # Convert nil to appropriate boolean: true if API key provided, false otherwise + tls = !api_key.nil? if tls.nil? @options = Options.new( target_host:, diff --git a/temporalio/test/client_connection_test.rb b/temporalio/test/client_connection_test.rb index 0aa4833c..a63bd708 100644 --- a/temporalio/test/client_connection_test.rb +++ b/temporalio/test/client_connection_test.rb @@ -29,17 +29,6 @@ def test_connection_tls_can_be_explicitly_disabled_with_api_key assert_equal false, connection.options.tls end - def test_connection_tls_disabled_by_default_without_api_key - # Test that TLS is disabled by default when no API key is provided - connection = Temporalio::Client::Connection.new( - target_host: 'localhost:7233', - lazy_connect: true - ) - - # TLS should remain nil (falsy) when no api_key is provided - refute connection.options.tls - end - def test_connection_explicit_tls_config_preserved_with_api_key # Test that explicit TLS configuration is preserved regardless of API key tls_options = Temporalio::Client::Connection::TLSOptions.new( From b9c418a3946c7958bf49637773ce52f8afdaadf6 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Wed, 3 Dec 2025 10:54:53 -0800 Subject: [PATCH 3/4] update sig files, push tls/api key check to bridge options construction --- .../lib/temporalio/client/connection.rb | 25 ++++++++++--------- temporalio/sig/temporalio/client.rbs | 2 +- .../sig/temporalio/client/connection.rbs | 6 ++--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/temporalio/lib/temporalio/client/connection.rb b/temporalio/lib/temporalio/client/connection.rb index 8a565bb4..21bb8e59 100644 --- a/temporalio/lib/temporalio/client/connection.rb +++ b/temporalio/lib/temporalio/client/connection.rb @@ -154,8 +154,9 @@ class HTTPConnectProxyOptions; end # rubocop:disable Lint/EmptyClass # +localhost:7233+. # @param api_key [String, nil] API key for Temporal. This becomes the +Authorization+ HTTP header with +"Bearer "+ # prepended. This is only set if RPC metadata doesn't already have an +authorization+ key. - # @param tls [Boolean, TLSOptions] If false, do not use TLS. If true, use system default TLS options. If TLS - # options are present, those TLS options will be used. + # @param tls [Boolean, TLSOptions, nil] If false, do not use TLS. If true, use system default TLS options. If TLS + # options are present, those TLS options will be used. If nil (the default), TLS will be auto-enabled if + # api_key is provided. # @param rpc_metadata [Hash] Headers to use for all calls to the server. Keys here can be # overriden by per-call RPC metadata keys. # @param rpc_retry [RPCRetryOptions] Retry options for direct service calls (when opted in) or all high-level @@ -182,10 +183,6 @@ def initialize( runtime: Runtime.default, lazy_connect: false ) - # Auto-enable TLS when API key provided and tls not explicitly set - # Convert nil to appropriate boolean: true if API key provided, false otherwise - tls = !api_key.nil? if tls.nil? - @options = Options.new( target_host:, api_key:, @@ -289,13 +286,17 @@ def new_core_client ), identity: @options.identity || "#{Process.pid}@#{Socket.gethostname}" ) - if @options.tls - options.tls = if @options.tls.is_a?(TLSOptions) + # Auto-enable TLS when API key is provided and tls not explicitly set + tls = @options.tls + tls = true if tls.nil? && @options.api_key + + if tls + options.tls = if tls.is_a?(TLSOptions) Internal::Bridge::Client::TLSOptions.new( - client_cert: @options.tls.client_cert, # steep:ignore - client_private_key: @options.tls.client_private_key, # steep:ignore - server_root_ca_cert: @options.tls.server_root_ca_cert, # steep:ignore - domain: @options.tls.domain # steep:ignore + client_cert: tls.client_cert, # steep:ignore + client_private_key: tls.client_private_key, # steep:ignore + server_root_ca_cert: tls.server_root_ca_cert, # steep:ignore + domain: tls.domain # steep:ignore ) else Internal::Bridge::Client::TLSOptions.new diff --git a/temporalio/sig/temporalio/client.rbs b/temporalio/sig/temporalio/client.rbs index 84a63d42..e40e9892 100644 --- a/temporalio/sig/temporalio/client.rbs +++ b/temporalio/sig/temporalio/client.rbs @@ -36,7 +36,7 @@ module Temporalio String target_host, String namespace, ?api_key: String?, - ?tls: bool | Connection::TLSOptions, + ?tls: bool | Connection::TLSOptions | nil, ?data_converter: Converters::DataConverter, ?interceptors: Array[Interceptor], ?logger: Logger, diff --git a/temporalio/sig/temporalio/client/connection.rbs b/temporalio/sig/temporalio/client/connection.rbs index 0c00d06e..1c43016a 100644 --- a/temporalio/sig/temporalio/client/connection.rbs +++ b/temporalio/sig/temporalio/client/connection.rbs @@ -4,7 +4,7 @@ module Temporalio class Options attr_reader target_host: String attr_reader api_key: String? - attr_reader tls: bool | Connection::TLSOptions + attr_reader tls: bool | Connection::TLSOptions | nil attr_reader rpc_metadata: Hash[String, String] attr_reader rpc_retry: RPCRetryOptions attr_reader identity: String @@ -16,7 +16,7 @@ module Temporalio def initialize: ( target_host: String, api_key: String?, - tls: bool | Connection::TLSOptions, + tls: bool | Connection::TLSOptions | nil, rpc_metadata: Hash[String, String], rpc_retry: RPCRetryOptions, identity: String, @@ -98,7 +98,7 @@ module Temporalio def initialize: ( target_host: String, ?api_key: String?, - ?tls: bool | Connection::TLSOptions, + ?tls: bool | Connection::TLSOptions | nil, ?rpc_metadata: Hash[String, String], ?rpc_retry: RPCRetryOptions, ?identity: String, From 22b9ed88d175f7a26977f1d779437488f08a0636 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Wed, 3 Dec 2025 11:38:29 -0800 Subject: [PATCH 4/4] change cloud tests to use api key to enable TLS --- temporalio/test/client_cloud_test.rb | 7 ++-- temporalio/test/client_connection_test.rb | 49 ----------------------- 2 files changed, 4 insertions(+), 52 deletions(-) delete mode 100644 temporalio/test/client_connection_test.rb diff --git a/temporalio/test/client_cloud_test.rb b/temporalio/test/client_cloud_test.rb index 264661ec..067cd6f4 100644 --- a/temporalio/test/client_cloud_test.rb +++ b/temporalio/test/client_cloud_test.rb @@ -28,6 +28,8 @@ def test_mtls end def test_api_key + # This test validates the auto-TLS feature: TLS is auto-enabled when api_key is provided + # and tls is not explicitly set. api_key = ENV.fetch('TEMPORAL_CLOUD_API_KEY_TEST_API_KEY', '') skip('No cloud API key') if api_key.empty? @@ -35,7 +37,6 @@ def test_api_key ENV.fetch('TEMPORAL_CLOUD_API_KEY_TEST_TARGET_HOST'), ENV.fetch('TEMPORAL_CLOUD_API_KEY_TEST_NAMESPACE'), api_key:, - tls: true, rpc_metadata: { 'temporal-namespace' => ENV.fetch('TEMPORAL_CLOUD_API_KEY_TEST_NAMESPACE') } ) # Run workflow @@ -52,14 +53,14 @@ def test_api_key end def test_cloud_ops + # This test also validates auto-TLS: TLS is auto-enabled when api_key is provided. api_key = ENV.fetch('TEMPORAL_CLOUD_OPS_TEST_API_KEY', '') skip('No cloud API key') if api_key.empty? - # Create connection + # Create connection (tls not set, auto-enabled due to api_key) conn = Temporalio::Client::Connection.new( target_host: ENV.fetch('TEMPORAL_CLOUD_OPS_TEST_TARGET_HOST'), api_key:, - tls: true, rpc_metadata: { 'temporal-cloud-api-version' => ENV.fetch('TEMPORAL_CLOUD_OPS_TEST_API_VERSION') } ) diff --git a/temporalio/test/client_connection_test.rb b/temporalio/test/client_connection_test.rb deleted file mode 100644 index a63bd708..00000000 --- a/temporalio/test/client_connection_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true - -require 'temporalio/client/connection' -require 'test' - -class ClientConnectionTest < Test - def test_connection_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 - connection = Temporalio::Client::Connection.new( - target_host: 'localhost:7233', - api_key: 'test-api-key', - lazy_connect: true - ) - - # TLS should be auto-enabled when api_key is provided and tls not explicitly set - assert_equal true, connection.options.tls - end - - def test_connection_tls_can_be_explicitly_disabled_with_api_key - # Test that TLS can be explicitly disabled even when API key is provided - connection = Temporalio::Client::Connection.new( - target_host: 'localhost:7233', - api_key: 'test-api-key', - tls: false, - lazy_connect: true - ) - - # TLS should remain disabled when explicitly set to false - assert_equal false, connection.options.tls - end - - def test_connection_explicit_tls_config_preserved_with_api_key - # Test that explicit TLS configuration is preserved regardless of API key - tls_options = Temporalio::Client::Connection::TLSOptions.new( - server_root_ca_cert: 'test-cert', - domain: 'test-domain' - ) - - connection = Temporalio::Client::Connection.new( - target_host: 'localhost:7233', - api_key: 'test-api-key', - tls: tls_options, - lazy_connect: true - ) - - # Explicit TLS config should be preserved - assert_equal tls_options, connection.options.tls - end -end