Skip to content

Commit 5e7a7b6

Browse files
feat: support mtls env variables
1 parent 299393b commit 5e7a7b6

File tree

11 files changed

+362
-536
lines changed

11 files changed

+362
-536
lines changed

gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/client.py.j2

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ from google.api_core import gapic_v1 # type: ignore
1313
from google.api_core import retry as retries # type: ignore
1414
from google.auth import credentials # type: ignore
1515
from google.auth.transport import mtls # type: ignore
16+
from google.auth.transport.grpc import SslCredentials # type: ignore
1617
from google.auth.exceptions import MutualTLSChannelError # type: ignore
1718
from google.oauth2 import service_account # type: ignore
1819

20+
import grpc # type: ignore
21+
1922
{% filter sort_lines -%}
2023
{% for method in service.methods.values() -%}
2124
{% for ref_type in method.flat_ref_types -%}
@@ -151,16 +154,19 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
151154
client_options (ClientOptions): Custom options for the client. It
152155
won't take effect unless ``transport`` is None.
153156
(1) The ``api_endpoint`` property can be used to override the
154-
default endpoint provided by the client. GOOGLE_API_USE_MTLS
157+
default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
155158
environment variable can also be used to override the endpoint:
156159
"always" (always use the default mTLS endpoint), "never" (always
157-
use the default regular endpoint, this is the default value for
158-
the environment variable) and "auto" (auto switch to the default
159-
mTLS endpoint if client SSL credentials is present). However,
160-
the ``api_endpoint`` property takes precedence if provided.
161-
(2) The ``client_cert_source`` property is used to provide client
162-
SSL credentials for mutual TLS transport. If not provided, the
163-
default SSL credentials will be used if present.
160+
use the default regular endpoint) and "auto" (auto switch to the
161+
default mTLS endpoint if client certificate is present, this is
162+
the default value). However, the ``api_endpoint`` property takes
163+
precedence if provided.
164+
(2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
165+
is "true", then the ``client_cert_source`` property can be used
166+
to provide client certificate for mutual TLS transport. If
167+
not provided, the default SSL client certificate will be used if
168+
present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
169+
set, no client certificate will be used.
164170
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
165171
The client info used to send a user-agent string along with
166172
API requests. If ``None``, then default info will be used.
@@ -175,24 +181,42 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
175181
client_options = ClientOptions.from_dict(client_options)
176182
if client_options is None:
177183
client_options = ClientOptions.ClientOptions()
184+
185+
# Create SSL credentials for mutual TLS if needed.
186+
use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
187+
if not use_client_cert in ["true", "false"]:
188+
raise MutualTLSChannelError(
189+
"Unsupported GOOGLE_API_USE_CLIENT_CERTIFICATE value. Accepted values: true, false"
190+
)
191+
192+
ssl_credentials = None
193+
is_mtls = False
194+
if use_client_cert == "true":
195+
if client_options.client_cert_source:
196+
cert, key = client_options.client_cert_source()
197+
ssl_credentials = grpc.ssl_channel_credentials(
198+
certificate_chain=cert, private_key=key
199+
)
200+
is_mtls = True
201+
else:
202+
creds = SslCredentials()
203+
is_mtls = creds.is_mtls
204+
ssl_credentials = creds.ssl_credentials if is_mtls else None
178205

179-
if transport is None and client_options.api_endpoint is None:
180-
use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never")
206+
# Figure out which api endpoint to use.
207+
if client_options.api_endpoint is not None:
208+
api_endpoint = client_options.api_endpoint
209+
else:
210+
use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
181211
if use_mtls_env == "never":
182-
client_options.api_endpoint = self.DEFAULT_ENDPOINT
212+
api_endpoint = self.DEFAULT_ENDPOINT
183213
elif use_mtls_env == "always":
184-
client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT
214+
api_endpoint = self.DEFAULT_MTLS_ENDPOINT
185215
elif use_mtls_env == "auto":
186-
has_client_cert_source = (
187-
client_options.client_cert_source is not None
188-
or mtls.has_default_client_cert_source()
189-
)
190-
client_options.api_endpoint = (
191-
self.DEFAULT_MTLS_ENDPOINT if has_client_cert_source else self.DEFAULT_ENDPOINT
192-
)
216+
api_endpoint = self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT
193217
else:
194218
raise MutualTLSChannelError(
195-
"Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always"
219+
"Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always"
196220
)
197221

198222
# Save or instantiate the transport.
@@ -212,9 +236,8 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
212236
else:
213237
self._transport = {{ service.name }}GrpcTransport(
214238
credentials=credentials,
215-
host=client_options.api_endpoint,
216-
api_mtls_endpoint=client_options.api_endpoint,
217-
client_cert_source=client_options.client_cert_source,
239+
host=api_endpoint,
240+
ssl_channel_credentials=ssl_credentials,
218241
client_info=client_info,
219242
)
220243

gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/grpc.py.j2

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ from google.api_core import operations_v1 # type: ignore
1010
from google.api_core import gapic_v1 # type: ignore
1111
from google import auth # type: ignore
1212
from google.auth import credentials # type: ignore
13-
from google.auth.transport.grpc import SslCredentials # type: ignore
1413

1514

1615
import grpc # type: ignore
@@ -40,8 +39,7 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
4039
host: str{% if service.host %} = '{{ service.host }}'{% endif %},
4140
credentials: credentials.Credentials = None,
4241
channel: grpc.Channel = None,
43-
api_mtls_endpoint: str = None,
44-
client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
42+
ssl_channel_credentials: grpc.ChannelCredentials = None,
4543
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
4644
) -> None:
4745
"""Instantiate the transport.
@@ -57,14 +55,8 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
5755
This argument is ignored if ``channel`` is provided.
5856
channel (Optional[grpc.Channel]): A ``Channel`` instance through
5957
which to make calls.
60-
api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If
61-
provided, it overrides the ``host`` argument and tries to create
62-
a mutual TLS channel with client SSL credentials from
63-
``client_cert_source`` or applicatin default SSL credentials.
64-
client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A
65-
callback to provide client SSL certificate bytes and private key
66-
bytes, both in PEM format. It is ignored if ``api_mtls_endpoint``
67-
is None.
58+
ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
59+
for grpc channel. It is ignored if ``channel`` is provided.
6860
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
6961
The client info used to send a user-agent string along with
7062
API requests. If ``None``, then default info will be used.
@@ -82,27 +74,17 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
8274

8375
# If a channel was explicitly provided, set it.
8476
self._grpc_channel = channel
85-
elif api_mtls_endpoint:
86-
host = api_mtls_endpoint if ":" in api_mtls_endpoint else api_mtls_endpoint + ":443"
77+
else:
78+
host = host if ":" in host else host + ":443"
8779

8880
if credentials is None:
8981
credentials, _ = auth.default(scopes=self.AUTH_SCOPES)
9082

91-
# Create SSL credentials with client_cert_source or application
92-
# default SSL credentials.
93-
if client_cert_source:
94-
cert, key = client_cert_source()
95-
ssl_credentials = grpc.ssl_channel_credentials(
96-
certificate_chain=cert, private_key=key
97-
)
98-
else:
99-
ssl_credentials = SslCredentials().ssl_credentials
100-
10183
# create a new channel. The provided one is ignored.
10284
self._grpc_channel = grpc_helpers.create_channel(
10385
host,
10486
credentials=credentials,
105-
ssl_credentials=ssl_credentials,
87+
ssl_credentials=ssl_channel_credentials,
10688
scopes=self.AUTH_SCOPES,
10789
)
10890

gapic/ads-templates/setup.py.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ setuptools.setup(
1616
platforms='Posix; MacOS X; Windows',
1717
include_package_data=True,
1818
install_requires=(
19-
'google-api-core >= 1.17.0, < 2.0.0dev',
19+
'google-api-core >= 1.22.2, < 2.0.0dev',
2020
'googleapis-common-protos >= 1.5.8',
2121
'grpcio >= 1.10.0',
2222
'proto-plus >= 1.4.0',

0 commit comments

Comments
 (0)