Uh oh!
There was an error while loading. Please reload this page.
This repository was archived by the owner on Mar 31, 2026. It is now read-only.
- Notifications
You must be signed in to change notification settings - Fork 173
feat: add mtls support#367
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
01a97a2
feat: add mtls support
arithmetic1728 24346f8
update
arithmetic1728 d128360
update
arithmetic1728 8562cf2
update
arithmetic1728 2325031
Merge branch 'master' into for_mtls
arithmetic1728 dca4785
update
arithmetic1728 e47027b
Merge branch 'master' into for_mtls
arithmetic1728 85f64fd
update
arithmetic1728 c16f762
Merge branch 'for_mtls' of https://github.com/googleapis/python-stora…
arithmetic1728 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -15,27 +15,42 @@ | ||
| """Create / interact with Google Cloud Storage connections.""" | ||
| import functools | ||
| import os | ||
| import pkg_resources | ||
| from google.cloud import _http | ||
| from google.cloud.storage import __version__ | ||
| if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE") == "true": # pragma: NO COVER | ||
| release = pkg_resources.get_distribution("google-cloud-core").parsed_version | ||
| if release < pkg_resources.parse_version("1.6.0"): | ||
arithmetic1728 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| raise ImportError("google-cloud-core >= 1.6.0 is required to use mTLS feature") | ||
| class Connection(_http.JSONConnection): | ||
| """A connection to Google Cloud Storage via the JSON REST API. | ||
| """A connection to Google Cloud Storage via the JSON REST API. Mutual TLS feature will be | ||
| enabled if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true". | ||
| :type client: :class:`~google.cloud.storage.client.Client` | ||
| :param client: The client that owns the current connection. | ||
| :type client_info: :class:`~google.api_core.client_info.ClientInfo` | ||
| :param client_info: (Optional) instance used to generate user agent. | ||
| :type api_endpoint: str | ||
| :param api_endpoint: (Optional) api endpoint to use. | ||
| """ | ||
| DEFAULT_API_ENDPOINT = "https://storage.googleapis.com" | ||
| DEFAULT_API_MTLS_ENDPOINT = "https://storage.mtls.googleapis.com" | ||
| def __init__(self, client, client_info=None, api_endpoint=DEFAULT_API_ENDPOINT): | ||
| def __init__(self, client, client_info=None, api_endpoint=None): | ||
| super(Connection, self).__init__(client, client_info) | ||
| self.API_BASE_URL = api_endpoint | ||
| self.API_BASE_URL = api_endpoint or self.DEFAULT_API_ENDPOINT | ||
| self.API_BASE_MTLS_URL = self.DEFAULT_API_MTLS_ENDPOINT | ||
| self.ALLOW_AUTO_SWITCH_TO_MTLS_URL = api_endpoint is None | ||
| self._client_info.client_library_version = __version__ | ||
| # TODO: When metrics all use gccl, this should be removed #9552 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -81,6 +81,7 @@ class Config(object): | ||
| CLIENT = None | ||
| TEST_BUCKET = None | ||
| TESTING_MTLS = False | ||
| def setUpModule(): | ||
| @@ -91,6 +92,10 @@ def setUpModule(): | ||
| Config.TEST_BUCKET = Config.CLIENT.bucket(bucket_name) | ||
| Config.TEST_BUCKET.versioning_enabled = True | ||
| retry_429_503(Config.TEST_BUCKET.create)() | ||
| # mTLS testing uses the system test as well. For mTLS testing, | ||
| # GOOGLE_API_USE_CLIENT_CERTIFICATE env var will be set to "true" | ||
| # explicitly. | ||
| Config.TESTING_MTLS = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE") == "true" | ||
| def tearDownModule(): | ||
| @@ -101,6 +106,15 @@ def tearDownModule(): | ||
| class TestClient(unittest.TestCase): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| super(TestClient, cls).setUpClass() | ||
| if ( | ||
| type(Config.CLIENT._credentials) | ||
| is not google.oauth2.service_account.Credentials | ||
| ): | ||
| raise unittest.SkipTest("These tests require a service account credential") | ||
| def setUp(self): | ||
| self.case_hmac_keys_to_delete = [] | ||
| @@ -563,6 +577,15 @@ def tearDown(self): | ||
| class TestStorageWriteFiles(TestStorageFiles): | ||
| ENCRYPTION_KEY = "b23ff11bba187db8c37077e6af3b25b8" | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| super(TestStorageWriteFiles, cls).setUpClass() | ||
| if ( | ||
| type(Config.CLIENT._credentials) | ||
| is not google.oauth2.service_account.Credentials | ||
| ): | ||
| raise unittest.SkipTest("These tests require a service account credential") | ||
| def test_large_file_write_from_stream(self): | ||
| blob = self.bucket.blob("LargeFile") | ||
| @@ -1285,11 +1308,14 @@ class TestStorageSignURLs(unittest.TestCase): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| super(TestStorageSignURLs, cls).setUpClass() | ||
| if ( | ||
| type(Config.CLIENT._credentials) | ||
| is not google.oauth2.service_account.Credentials | ||
| ): | ||
| cls.skipTest("Signing tests requires a service account credential") | ||
| raise unittest.SkipTest( | ||
| "Signing tests requires a service account credential" | ||
| ) | ||
| bucket_name = "gcp-signing" + unique_resource_id() | ||
| cls.bucket = retry_429_503(Config.CLIENT.create_bucket)(bucket_name) | ||
| @@ -1850,6 +1876,18 @@ class TestStorageNotificationCRUD(unittest.TestCase): | ||
| CUSTOM_ATTRIBUTES = {"attr1": "value1", "attr2": "value2"} | ||
| BLOB_NAME_PREFIX = "blob-name-prefix/" | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| super(TestStorageNotificationCRUD, cls).setUpClass() | ||
| if Config.TESTING_MTLS: | ||
| # mTLS is only available for python-pubsub >= 2.2.0. However, the | ||
| # system test uses python-pubsub < 2.0, so we skip those tests. | ||
| # Note that python-pubsub >= 2.0 no longer supports python 2.7, so | ||
| # we can only upgrade it after python 2.7 system test is removed. | ||
| # Since python-pubsub >= 2.0 has a new set of api, the test code | ||
| # also needs to be updated. | ||
| raise unittest.SkipTest("Skip pubsub tests for mTLS testing") | ||
| @property | ||
| def topic_path(self): | ||
| return "projects/{}/topics/{}".format(Config.CLIENT.project, self.TOPIC_NAME) | ||
| @@ -2013,6 +2051,15 @@ def _kms_key_name(self, key_name=None): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| super(TestKMSIntegration, cls).setUpClass() | ||
| if Config.TESTING_MTLS: | ||
| # mTLS is only available for python-kms >= 2.2.0. However, the | ||
| # system test uses python-kms < 2.0, so we skip those tests. | ||
| # Note that python-kms >= 2.0 no longer supports python 2.7, so | ||
| # we can only upgrade it after python 2.7 system test is removed. | ||
| # Since python-kms >= 2.0 has a new set of api, the test code | ||
| # also needs to be updated. | ||
| raise unittest.SkipTest("Skip kms tests for mTLS testing") | ||
arithmetic1728 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| _empty_bucket(Config.CLIENT, cls.bucket) | ||
| def setUp(self): | ||
| @@ -2466,6 +2513,17 @@ def test_ubla_set_unset_preserves_acls(self): | ||
| class TestV4POSTPolicies(unittest.TestCase): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| super(TestV4POSTPolicies, cls).setUpClass() | ||
| if ( | ||
| type(Config.CLIENT._credentials) | ||
| is not google.oauth2.service_account.Credentials | ||
| ): | ||
| # mTLS only works for user credentials, it doesn't work for | ||
| # service account credentials. | ||
| raise unittest.SkipTest("These tests require a service account credential") | ||
arithmetic1728 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| def setUp(self): | ||
| self.case_buckets_to_delete = [] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -25,6 +25,8 @@ def _get_target_class(): | ||
| return Connection | ||
| def _make_one(self, *args, **kw): | ||
| if "api_endpoint" not in kw: | ||
| kw["api_endpoint"] = "https://storage.googleapis.com" | ||
| return self._get_target_class()(*args, **kw) | ||
| def test_extra_headers(self): | ||
| @@ -213,3 +215,16 @@ def test_api_request_conditional_retry_failed(self): | ||
| retry=conditional_retry_mock, | ||
| ) | ||
| http.request.assert_called_once() | ||
| def test_mtls(self): | ||
| client = object() | ||
| conn = self._make_one(client, api_endpoint=None) | ||
| self.assertEqual(conn.ALLOW_AUTO_SWITCH_TO_MTLS_URL, True) | ||
| self.assertEqual(conn.API_BASE_URL, "https://storage.googleapis.com") | ||
| self.assertEqual(conn.API_BASE_MTLS_URL, "https://storage.mtls.googleapis.com") | ||
| conn = self._make_one(client, api_endpoint="http://foo") | ||
| self.assertEqual(conn.ALLOW_AUTO_SWITCH_TO_MTLS_URL, False) | ||
| self.assertEqual(conn.API_BASE_URL, "http://foo") | ||
| self.assertEqual(conn.API_BASE_MTLS_URL, "https://storage.mtls.googleapis.com") | ||
arithmetic1728 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.