@@ -148,12 +148,19 @@ def test__read_environment_variables():
148148 with mock .patch .dict (
149149 os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "Unsupported" }
150150 ):
151- with pytest .raises (ValueError ) as excinfo :
152- StorageClient ._read_environment_variables ()
153- assert (
154- str (excinfo .value )
155- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
156- )
151+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
152+ with pytest .raises (ValueError ) as excinfo :
153+ StorageClient ._read_environment_variables ()
154+ assert (
155+ str (excinfo .value )
156+ == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
157+ )
158+ else :
159+ assert StorageClient ._read_environment_variables () == (
160+ False ,
161+ "auto" ,
162+ None ,
163+ )
157164
158165 with mock .patch .dict (os .environ , {"GOOGLE_API_USE_MTLS_ENDPOINT" : "never" }):
159166 assert StorageClient ._read_environment_variables () == (False , "never" , None )
@@ -176,6 +183,105 @@ def test__read_environment_variables():
176183 assert StorageClient ._read_environment_variables () == (False , "auto" , "foo.com" )
177184
178185
186+ def test_use_client_cert_effective ():
187+ # Test case 1: Test when `should_use_client_cert` returns True.
188+ # We mock the `should_use_client_cert` function to simulate a scenario where
189+ # the google-auth library supports automatic mTLS and determines that a
190+ # client certificate should be used.
191+ if hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
192+ with mock .patch (
193+ "google.auth.transport.mtls.should_use_client_cert" , return_value = True
194+ ):
195+ assert StorageClient ._use_client_cert_effective () is True
196+
197+ # Test case 2: Test when `should_use_client_cert` returns False.
198+ # We mock the `should_use_client_cert` function to simulate a scenario where
199+ # the google-auth library supports automatic mTLS and determines that a
200+ # client certificate should NOT be used.
201+ if hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
202+ with mock .patch (
203+ "google.auth.transport.mtls.should_use_client_cert" , return_value = False
204+ ):
205+ assert StorageClient ._use_client_cert_effective () is False
206+
207+ # Test case 3: Test when `should_use_client_cert` is unavailable and the
208+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true".
209+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
210+ with mock .patch .dict (os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "true" }):
211+ assert StorageClient ._use_client_cert_effective () is True
212+
213+ # Test case 4: Test when `should_use_client_cert` is unavailable and the
214+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "false".
215+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
216+ with mock .patch .dict (
217+ os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "false" }
218+ ):
219+ assert StorageClient ._use_client_cert_effective () is False
220+
221+ # Test case 5: Test when `should_use_client_cert` is unavailable and the
222+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "True".
223+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
224+ with mock .patch .dict (os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "True" }):
225+ assert StorageClient ._use_client_cert_effective () is True
226+
227+ # Test case 6: Test when `should_use_client_cert` is unavailable and the
228+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "False".
229+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
230+ with mock .patch .dict (
231+ os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "False" }
232+ ):
233+ assert StorageClient ._use_client_cert_effective () is False
234+
235+ # Test case 7: Test when `should_use_client_cert` is unavailable and the
236+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "TRUE".
237+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
238+ with mock .patch .dict (os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "TRUE" }):
239+ assert StorageClient ._use_client_cert_effective () is True
240+
241+ # Test case 8: Test when `should_use_client_cert` is unavailable and the
242+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "FALSE".
243+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
244+ with mock .patch .dict (
245+ os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "FALSE" }
246+ ):
247+ assert StorageClient ._use_client_cert_effective () is False
248+
249+ # Test case 9: Test when `should_use_client_cert` is unavailable and the
250+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not set.
251+ # In this case, the method should return False, which is the default value.
252+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
253+ with mock .patch .dict (os .environ , clear = True ):
254+ assert StorageClient ._use_client_cert_effective () is False
255+
256+ # Test case 10: Test when `should_use_client_cert` is unavailable and the
257+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
258+ # The method should raise a ValueError as the environment variable must be either
259+ # "true" or "false".
260+ if not hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
261+ with mock .patch .dict (
262+ os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "unsupported" }
263+ ):
264+ with pytest .raises (ValueError ):
265+ StorageClient ._use_client_cert_effective ()
266+
267+ # Test case 11: Test when `should_use_client_cert` is available and the
268+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
269+ # The method should return False as the environment variable is set to an invalid value.
270+ if hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
271+ with mock .patch .dict (
272+ os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "unsupported" }
273+ ):
274+ assert StorageClient ._use_client_cert_effective () is False
275+
276+ # Test case 12: Test when `should_use_client_cert` is available and the
277+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is unset. Also,
278+ # the GOOGLE_API_CONFIG environment variable is unset.
279+ if hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
280+ with mock .patch .dict (os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "" }):
281+ with mock .patch .dict (os .environ , {"GOOGLE_API_CERTIFICATE_CONFIG" : "" }):
282+ assert StorageClient ._use_client_cert_effective () is False
283+
284+
179285def test__get_client_cert_source ():
180286 mock_provided_cert_source = mock .Mock ()
181287 mock_default_cert_source = mock .Mock ()
@@ -515,17 +621,6 @@ def test_storage_client_client_options(client_class, transport_class, transport_
515621 == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
516622 )
517623
518- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
519- with mock .patch .dict (
520- os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "Unsupported" }
521- ):
522- with pytest .raises (ValueError ) as excinfo :
523- client = client_class (transport = transport_name )
524- assert (
525- str (excinfo .value )
526- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
527- )
528-
529624 # Check the case quota_project_id is provided
530625 options = client_options .ClientOptions (quota_project_id = "octopus" )
531626 with mock .patch .object (transport_class , "__init__" ) as patched :
@@ -733,6 +828,119 @@ def test_storage_client_get_mtls_endpoint_and_cert_source(client_class):
733828 assert api_endpoint == mock_api_endpoint
734829 assert cert_source is None
735830
831+ # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "Unsupported".
832+ with mock .patch .dict (
833+ os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "Unsupported" }
834+ ):
835+ if hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
836+ mock_client_cert_source = mock .Mock ()
837+ mock_api_endpoint = "foo"
838+ options = client_options .ClientOptions (
839+ client_cert_source = mock_client_cert_source ,
840+ api_endpoint = mock_api_endpoint ,
841+ )
842+ api_endpoint , cert_source = client_class .get_mtls_endpoint_and_cert_source (
843+ options
844+ )
845+ assert api_endpoint == mock_api_endpoint
846+ assert cert_source is None
847+
848+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset.
849+ test_cases = [
850+ (
851+ # With workloads present in config, mTLS is enabled.
852+ {
853+ "version" : 1 ,
854+ "cert_configs" : {
855+ "workload" : {
856+ "cert_path" : "path/to/cert/file" ,
857+ "key_path" : "path/to/key/file" ,
858+ }
859+ },
860+ },
861+ mock_client_cert_source ,
862+ ),
863+ (
864+ # With workloads not present in config, mTLS is disabled.
865+ {
866+ "version" : 1 ,
867+ "cert_configs" : {},
868+ },
869+ None ,
870+ ),
871+ ]
872+ if hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
873+ for config_data , expected_cert_source in test_cases :
874+ env = os .environ .copy ()
875+ env .pop ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , None )
876+ with mock .patch .dict (os .environ , env , clear = True ):
877+ config_filename = "mock_certificate_config.json"
878+ config_file_content = json .dumps (config_data )
879+ m = mock .mock_open (read_data = config_file_content )
880+ with mock .patch ("builtins.open" , m ):
881+ with mock .patch .dict (
882+ os .environ , {"GOOGLE_API_CERTIFICATE_CONFIG" : config_filename }
883+ ):
884+ mock_api_endpoint = "foo"
885+ options = client_options .ClientOptions (
886+ client_cert_source = mock_client_cert_source ,
887+ api_endpoint = mock_api_endpoint ,
888+ )
889+ (
890+ api_endpoint ,
891+ cert_source ,
892+ ) = client_class .get_mtls_endpoint_and_cert_source (options )
893+ assert api_endpoint == mock_api_endpoint
894+ assert cert_source is expected_cert_source
895+
896+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset(empty).
897+ test_cases = [
898+ (
899+ # With workloads present in config, mTLS is enabled.
900+ {
901+ "version" : 1 ,
902+ "cert_configs" : {
903+ "workload" : {
904+ "cert_path" : "path/to/cert/file" ,
905+ "key_path" : "path/to/key/file" ,
906+ }
907+ },
908+ },
909+ mock_client_cert_source ,
910+ ),
911+ (
912+ # With workloads not present in config, mTLS is disabled.
913+ {
914+ "version" : 1 ,
915+ "cert_configs" : {},
916+ },
917+ None ,
918+ ),
919+ ]
920+ if hasattr (google .auth .transport .mtls , "should_use_client_cert" ):
921+ for config_data , expected_cert_source in test_cases :
922+ env = os .environ .copy ()
923+ env .pop ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "" )
924+ with mock .patch .dict (os .environ , env , clear = True ):
925+ config_filename = "mock_certificate_config.json"
926+ config_file_content = json .dumps (config_data )
927+ m = mock .mock_open (read_data = config_file_content )
928+ with mock .patch ("builtins.open" , m ):
929+ with mock .patch .dict (
930+ os .environ , {"GOOGLE_API_CERTIFICATE_CONFIG" : config_filename }
931+ ):
932+ mock_api_endpoint = "foo"
933+ options = client_options .ClientOptions (
934+ client_cert_source = mock_client_cert_source ,
935+ api_endpoint = mock_api_endpoint ,
936+ )
937+ (
938+ api_endpoint ,
939+ cert_source ,
940+ ) = client_class .get_mtls_endpoint_and_cert_source (options )
941+ assert api_endpoint == mock_api_endpoint
942+ assert cert_source is expected_cert_source
943+
736944 # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never".
737945 with mock .patch .dict (os .environ , {"GOOGLE_API_USE_MTLS_ENDPOINT" : "never" }):
738946 api_endpoint , cert_source = client_class .get_mtls_endpoint_and_cert_source ()
@@ -783,18 +991,6 @@ def test_storage_client_get_mtls_endpoint_and_cert_source(client_class):
783991 == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
784992 )
785993
786- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
787- with mock .patch .dict (
788- os .environ , {"GOOGLE_API_USE_CLIENT_CERTIFICATE" : "Unsupported" }
789- ):
790- with pytest .raises (ValueError ) as excinfo :
791- client_class .get_mtls_endpoint_and_cert_source ()
792-
793- assert (
794- str (excinfo .value )
795- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
796- )
797-
798994
799995@pytest .mark .parametrize ("client_class" , [StorageClient , StorageAsyncClient ])
800996@mock .patch .object (
0 commit comments