Skip to content

Commit bdc95f3

Browse files
committed
fix: deprecate credentials_file argument
1 parent 14a5978 commit bdc95f3

File tree

8 files changed

+114
-32
lines changed

8 files changed

+114
-32
lines changed

google/api_core/client_options.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def get_client_cert():
4949
"""
5050

5151
from typing import Callable, Mapping, Optional, Sequence, Tuple
52+
import warnings
53+
54+
from google.api_core import general_helpers
5255

5356

5457
class ClientOptions(object):
@@ -67,8 +70,9 @@ class ClientOptions(object):
6770
and ``client_encrypted_cert_source`` are mutually exclusive.
6871
quota_project_id (Optional[str]): A project name that a client's
6972
quota belongs to.
70-
credentials_file (Optional[str]): A path to a file storing credentials.
71-
``credentials_file` and ``api_key`` are mutually exclusive.
73+
credentials_file (Optional[str]): Deprecated. A path to a file storing credentials.
74+
``credentials_file` and ``api_key`` are mutually exclusive. This argument will be
75+
removed in the next major version of `google-api-core`.
7276
7377
.. warning::
7478
Important: If you accept a credential configuration (credential JSON/File/Stream)
@@ -114,6 +118,9 @@ def __init__(
114118
api_audience: Optional[str] = None,
115119
universe_domain: Optional[str] = None,
116120
):
121+
if credentials_file is not None:
122+
warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning)
123+
117124
if client_cert_source and client_encrypted_cert_source:
118125
raise ValueError(
119126
"client_cert_source and client_encrypted_cert_source are mutually exclusive"

google/api_core/general_helpers.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,36 @@
1414

1515
# This import for backward compatibility only.
1616
from functools import wraps # noqa: F401 pragma: NO COVER
17+
18+
_CREDENTIALS_FILE_WARNING = """\
19+
The `credentials_file` argument is deprecated because of a potential security risk.
20+
21+
The `google.auth.load_credentials_from_file` method does not validate the credential
22+
configuration. The security risk occurs when a credential configuration is accepted
23+
from a source that is not under your control and used without validation on your side.
24+
25+
If you know that you will be loading credential configurations of a
26+
specific type, it is recommended to use a credential-type-specific
27+
load method.
28+
29+
This will ensure that an unexpected credential type with potential for
30+
malicious intent is not loaded unintentionally. You might still have to do
31+
validation for certain credential types. Please follow the recommendations
32+
for that method. For example, if you want to load only service accounts,
33+
you can create the service account credentials explicitly:
34+
35+
```
36+
from google.oauth2 import service_account
37+
creds = service_account.Credentials.from_service_account_file(filename)
38+
```
39+
40+
If you are loading your credential configuration from an untrusted source and have
41+
not mitigated the risks (e.g. by validating the configuration yourself), make
42+
these changes as soon as possible to prevent security risks to your environment.
43+
44+
Regardless of the method used, it is always your responsibility to validate
45+
configurations received from external sources.
46+
47+
Refer to https://cloud.google.com/docs/authentication/external/externally-sourced-credentials
48+
for more details.
49+
"""

google/api_core/grpc_helpers.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,19 @@
1313
# limitations under the License.
1414

1515
"""Helpers for :mod:`grpc`."""
16-
from typing import Generic, Iterator, Optional, TypeVar
17-
1816
import collections
1917
import functools
18+
from typing import Generic, Iterator, Optional, TypeVar
2019
import warnings
2120

22-
import grpc
23-
24-
from google.api_core import exceptions
2521
import google.auth
2622
import google.auth.credentials
2723
import google.auth.transport.grpc
2824
import google.auth.transport.requests
2925
import google.protobuf
26+
import grpc
27+
28+
from google.api_core import exceptions, general_helpers
3029

3130
PROTOBUF_VERSION = google.protobuf.__version__
3231

@@ -213,9 +212,10 @@ def _create_composite_credentials(
213212
credentials (google.auth.credentials.Credentials): The credentials. If
214213
not specified, then this function will attempt to ascertain the
215214
credentials from the environment using :func:`google.auth.default`.
216-
credentials_file (str): A file with credentials that can be loaded with
215+
credentials_file (str): Deprecated. A file with credentials that can be loaded with
217216
:func:`google.auth.load_credentials_from_file`. This argument is
218-
mutually exclusive with credentials.
217+
mutually exclusive with credentials. This argument will be
218+
removed in the next major version of `google-api-core`.
219219
220220
.. warning::
221221
Important: If you accept a credential configuration (credential JSON/File/Stream)
@@ -245,6 +245,9 @@ def _create_composite_credentials(
245245
Raises:
246246
google.api_core.DuplicateCredentialArgs: If both a credentials object and credentials_file are passed.
247247
"""
248+
if credentials_file is not None:
249+
warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning)
250+
248251
if credentials and credentials_file:
249252
raise exceptions.DuplicateCredentialArgs(
250253
"'credentials' and 'credentials_file' are mutually exclusive."

google/api_core/grpc_helpers_async.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@
2020

2121
import asyncio
2222
import functools
23+
import warnings
2324

2425
from typing import AsyncGenerator, Generic, Iterator, Optional, TypeVar
2526

2627
import grpc
2728
from grpc import aio
2829

29-
from google.api_core import exceptions, grpc_helpers
30+
from google.api_core import exceptions, general_helpers, grpc_helpers
3031

3132
# denotes the proto response type for grpc calls
3233
P = TypeVar("P")
@@ -233,9 +234,10 @@ def create_channel(
233234
are passed to :func:`google.auth.default`.
234235
ssl_credentials (grpc.ChannelCredentials): Optional SSL channel
235236
credentials. This can be used to specify different certificates.
236-
credentials_file (str): A file with credentials that can be loaded with
237+
credentials_file (str): Deprecated. A file with credentials that can be loaded with
237238
:func:`google.auth.load_credentials_from_file`. This argument is
238-
mutually exclusive with credentials.
239+
mutually exclusive with credentials. This argument will be
240+
removed in the next major version of `google-api-core`.
239241
240242
.. warning::
241243
Important: If you accept a credential configuration (credential JSON/File/Stream)
@@ -280,6 +282,9 @@ def create_channel(
280282
ValueError: If `ssl_credentials` is set and `attempt_direct_path` is set to `True`.
281283
"""
282284

285+
if credentials_file is not None:
286+
warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning)
287+
283288
# If `ssl_credentials` is set and `attempt_direct_path` is set to `True`,
284289
# raise ValueError as this is not yet supported.
285290
# See https://github.com/googleapis/python-api-core/issues/590

google/api_core/operations_v1/transports/base.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,8 @@
1616
import abc
1717
import re
1818
from typing import Awaitable, Callable, Optional, Sequence, Union
19+
import warnings
1920

20-
import google.api_core # type: ignore
21-
from google.api_core import exceptions as core_exceptions # type: ignore
22-
from google.api_core import gapic_v1 # type: ignore
23-
from google.api_core import retry as retries # type: ignore
24-
from google.api_core import version
2521
import google.auth # type: ignore
2622
from google.auth import credentials as ga_credentials # type: ignore
2723
from google.longrunning import operations_pb2
@@ -30,6 +26,12 @@
3026
from google.protobuf import empty_pb2, json_format # type: ignore
3127
from grpc import Compression
3228

29+
import google.api_core # type: ignore
30+
from google.api_core import exceptions as core_exceptions # type: ignore
31+
from google.api_core import gapic_v1 # type: ignore
32+
from google.api_core import general_helpers
33+
from google.api_core import retry as retries # type: ignore
34+
from google.api_core import version
3335

3436
PROTOBUF_VERSION = google.protobuf.__version__
3537

@@ -69,9 +71,10 @@ def __init__(
6971
credentials identify the application to the service; if none
7072
are specified, the client will attempt to ascertain the
7173
credentials from the environment.
72-
credentials_file (Optional[str]): A file with credentials that can
74+
credentials_file (Optional[str]): Deprecated. A file with credentials that can
7375
be loaded with :func:`google.auth.load_credentials_from_file`.
74-
This argument is mutually exclusive with credentials.
76+
This argument is mutually exclusive with credentials. This argument will be
77+
removed in the next major version of `google-api-core`.
7578
7679
.. warning::
7780
Important: If you accept a credential configuration (credential JSON/File/Stream)
@@ -98,6 +101,9 @@ def __init__(
98101
"https", but for testing or local servers,
99102
"http" can be specified.
100103
"""
104+
if credentials_file is not None:
105+
warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning)
106+
101107
maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host)
102108
if maybe_url_match is None:
103109
raise ValueError(

google/api_core/operations_v1/transports/rest.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,26 @@
1515
#
1616

1717
from typing import Callable, Dict, Optional, Sequence, Tuple, Union
18+
import warnings
1819

20+
from google.auth import credentials as ga_credentials # type: ignore
21+
from google.auth.transport.requests import AuthorizedSession # type: ignore
22+
from google.longrunning import operations_pb2 # type: ignore
23+
import google.protobuf
24+
from google.protobuf import empty_pb2 # type: ignore
25+
from google.protobuf import json_format # type: ignore
26+
import grpc
1927
from requests import __version__ as requests_version
2028

2129
from google.api_core import exceptions as core_exceptions # type: ignore
2230
from google.api_core import gapic_v1 # type: ignore
31+
from google.api_core import general_helpers
2332
from google.api_core import path_template # type: ignore
2433
from google.api_core import rest_helpers # type: ignore
2534
from google.api_core import retry as retries # type: ignore
26-
from google.auth import credentials as ga_credentials # type: ignore
27-
from google.auth.transport.requests import AuthorizedSession # type: ignore
28-
from google.longrunning import operations_pb2 # type: ignore
29-
from google.protobuf import empty_pb2 # type: ignore
30-
from google.protobuf import json_format # type: ignore
31-
import google.protobuf
3235

33-
import grpc
34-
from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO, OperationsTransport
36+
from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO
37+
from .base import OperationsTransport
3538

3639
PROTOBUF_VERSION = google.protobuf.__version__
3740

@@ -91,19 +94,20 @@ def __init__(
9194
are specified, the client will attempt to ascertain the
9295
credentials from the environment.
9396
94-
credentials_file (Optional[str]): A file with credentials that can
97+
credentials_file (Optional[str]): Deprecated. A file with credentials that can
9598
be loaded with :func:`google.auth.load_credentials_from_file`.
96-
This argument is ignored if ``channel`` is provided.
99+
This argument is ignored if ``channel`` is provided. This argument will be
100+
removed in the next major version of `google-api-core`.
97101
98102
.. warning::
99103
Important: If you accept a credential configuration (credential JSON/File/Stream)
100104
from an external source for authentication to Google Cloud Platform, you must
101105
validate it before providing it to any Google API or client library. Providing an
102106
unvalidated credential configuration to Google APIs or libraries can compromise
103107
the security of your systems and data. For more information, refer to
104-
`Validate credential configurations from external sources`_.
108+
`Validate credential configuration from external sources`_.
105109
106-
.. _Validate credential configurations from external sources:
110+
.. _Validate credential configuration from external sources:
107111
108112
https://cloud.google.com/docs/authentication/external/externally-sourced-credentials
109113
scopes (Optional(Sequence[str])): A list of scopes. This argument is
@@ -130,6 +134,9 @@ def __init__(
130134
"v1" by default.
131135
132136
"""
137+
if credentials_file is not None:
138+
warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning)
139+
133140
# Run the base constructor
134141
# TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc.
135142
# TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the

google/api_core/operations_v1/transports/rest_asyncio.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import json
1818
from typing import Any, Callable, Coroutine, Dict, Optional, Sequence, Tuple
19+
import warnings
1920

2021
from google.auth import __version__ as auth_version
2122

@@ -29,6 +30,7 @@
2930

3031
from google.api_core import exceptions as core_exceptions # type: ignore
3132
from google.api_core import gapic_v1 # type: ignore
33+
from google.api_core import general_helpers
3234
from google.api_core import path_template # type: ignore
3335
from google.api_core import rest_helpers # type: ignore
3436
from google.api_core import retry_async as retries_async # type: ignore
@@ -96,6 +98,22 @@ def __init__(
9698
credentials identify the application to the service; if none
9799
are specified, the client will attempt to ascertain the
98100
credentials from the environment.
101+
credentials_file (Optional[str]): Deprecated. A file with credentials that can
102+
be loaded with :func:`google.auth.load_credentials_from_file`.
103+
This argument is ignored if ``channel`` is provided. This argument will be
104+
removed in the next major version of `google-api-core`.
105+
106+
.. warning::
107+
Important: If you accept a credential configuration (credential JSON/File/Stream)
108+
from an external source for authentication to Google Cloud Platform, you must
109+
validate it before providing it to any Google API or client library. Providing an
110+
unvalidated credential configuration to Google APIs or libraries can compromise
111+
the security of your systems and data. For more information, refer to
112+
`Validate credential configurations from external sources`_.
113+
114+
.. _Validate credential configurations from external sources:
115+
116+
https://cloud.google.com/docs/authentication/external/externally-sourced-credentials
99117
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
100118
The client info used to send a user-agent string along with
101119
API requests. If ``None``, then default info will be used.
@@ -113,6 +131,9 @@ def __init__(
113131
"v1" by default.
114132
115133
"""
134+
if credentials_file is not None:
135+
warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning)
136+
116137
unsupported_params = {
117138
# TODO(https://github.com/googleapis/python-api-core/issues/715): Add support for `credentials_file` to async REST transport.
118139
"google.api_core.client_options.ClientOptions.credentials_file": credentials_file,

tests/unit/operations_v1/test_operations_rest_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ def test_operations_client_client_options(
359359
client = client_class(client_options=options, transport=transport_name)
360360
patched.assert_called_once_with(
361361
credentials=None,
362-
credentials_file=None,
362+
credentials_file="credentials.json",
363363
host=client.DEFAULT_ENDPOINT,
364364
scopes=None,
365365
client_cert_source_for_mtls=None,

0 commit comments

Comments
 (0)