Skip to content

Commit b0eafcf

Browse files
Update grpc.py for cert rotation handling
1 parent 54a513a commit b0eafcf

File tree

1 file changed

+42
-59
lines changed
  • packages/google-auth/google/auth/transport

1 file changed

+42
-59
lines changed

packages/google-auth/google/auth/transport/grpc.py

Lines changed: 42 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
14+
1515
"""Authorization support for gRPC."""
16-
16+
1717
from __future__ import absolute_import
1818

1919
import logging
2020
import threading
2121
from google.auth import exceptions
2222
from google.auth.transport import _mtls_helper
2323
from google.oauth2 import service_account
24-
24+
2525
try:
2626
import grpc # type: ignore
2727
except ImportError as caught_exc: # pragma: NO COVER
@@ -30,17 +30,16 @@
3030
) from caught_exc
3131

3232
_LOGGER = logging.getLogger(__name__)
33-
3433

3534
class AuthMetadataPlugin(grpc.AuthMetadataPlugin):
3635
"""A `gRPC AuthMetadataPlugin`_ that inserts the credentials into each
3736
request.
38-
37+
3938
.. _gRPC AuthMetadataPlugin:
4039
http://www.grpc.io/grpc/python/grpc.html#grpc.AuthMetadataPlugin
41-
40+
4241
Args:
43-
credentials (google.auth.credentials.Credentials): The credentials to
42+
credentials (google.auth.credentials.Credentials): The credentials to
4443
add to requests.
4544
request (google.auth.transport.Request): A HTTP transport request
4645
object used to refresh credentials as needed.
@@ -57,7 +56,7 @@ def __init__(self, credentials, request, default_host=None):
5756
self._credentials = credentials
5857
self._request = request
5958
self._default_host = default_host
60-
59+
6160
def _get_authorization_headers(self, context):
6261
"""Gets the authorization headers for a request.
6362
@@ -66,7 +65,7 @@ def _get_authorization_headers(self, context):
6665
to add to the request.
6766
"""
6867
headers = {}
69-
68+
7069
# https://google.aip.dev/auth/4111
7170
# Attempt to use self-signed JWTs when a service account is used.
7271
# A default host must be explicitly provided since it cannot always
@@ -75,24 +74,24 @@ def _get_authorization_headers(self, context):
7574
self._credentials._create_self_signed_jwt(
7675
"https://{}/".format(self._default_host) if self._default_host else None
7776
)
78-
77+
7978
self._credentials.before_request(
8079
self._request, context.method_name, context.service_url, headers
8180
)
82-
81+
8382
return list(headers.items())
84-
83+
8584
def __call__(self, context, callback):
8685
"""Passes authorization metadata into the given callback.
87-
86+
8887
Args:
8988
context (grpc.AuthMetadataContext): The RPC context.
9089
callback (grpc.AuthMetadataPluginCallback): The callback that will
9190
be invoked to pass in the authorization metadata.
9291
"""
9392
callback(self._get_authorization_headers(context), None)
94-
95-
93+
94+
9695
def secure_authorized_channel(
9796
credentials,
9897
request,
@@ -102,20 +101,20 @@ def secure_authorized_channel(
102101
**kwargs
103102
):
104103
"""Creates a secure authorized gRPC channel.
105-
104+
106105
This creates a channel with SSL and :class:`AuthMetadataPlugin`. This
107106
channel can be used to create a stub that can make authorized requests.
108107
Users can configure client certificate or rely on device certificates to
109108
establish a mutual TLS channel, if the `GOOGLE_API_USE_CLIENT_CERTIFICATE`
110109
variable is explicitly set to `true`.
111110
112111
Example::
113-
112+
114113
import google.auth
115114
import google.auth.transport.grpc
116115
import google.auth.transport.requests
117116
from google.cloud.speech.v1 import cloud_speech_pb2
118-
117+
119118
# Get credentials.
120119
credentials, _ = google.auth.default()
121120
@@ -126,34 +125,34 @@ def secure_authorized_channel(
126125
channel = google.auth.transport.grpc.secure_authorized_channel(
127126
credentials, regular_endpoint, request,
128127
ssl_credentials=grpc.ssl_channel_credentials())
129-
128+
130129
# Use the channel to create a stub.
131130
cloud_speech.create_Speech_stub(channel)
132-
131+
133132
Usage:
134133
135134
There are actually a couple of options to create a channel, depending on if
136135
you want to create a regular or mutual TLS channel.
137136
138137
First let's list the endpoints (regular vs mutual TLS) to choose from::
139-
138+
140139
regular_endpoint = 'speech.googleapis.com:443'
141140
mtls_endpoint = 'speech.mtls.googleapis.com:443'
142-
141+
143142
Option 1: create a regular (non-mutual) TLS channel by explicitly setting
144143
the ssl_credentials::
145-
144+
146145
regular_ssl_credentials = grpc.ssl_channel_credentials()
147-
146+
148147
channel = google.auth.transport.grpc.secure_authorized_channel(
149148
credentials, request, regular_endpoint,
150149
ssl_credentials=regular_ssl_credentials)
151-
150+
152151
Option 2: create a mutual TLS channel by calling a callback which returns
153152
the client side certificate and the key (Note that
154153
`GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be explicitly
155154
set to `true`)::
156-
155+
157156
def my_client_cert_callback():
158157
code_to_load_client_cert_and_key()
159158
if loaded:
@@ -164,16 +163,16 @@ def my_client_cert_callback():
164163
channel = google.auth.transport.grpc.secure_authorized_channel(
165164
credentials, request, mtls_endpoint,
166165
client_cert_callback=my_client_cert_callback)
167-
except MyClientCertFailureException:
166+
except MyClientCertFailureException:
168167
# handle the exception
169-
168+
170169
Option 3: use application default SSL credentials. It searches and uses
171170
the command in a context aware metadata file, which is available on devices
172171
with endpoint verification support (Note that
173172
`GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be explicitly
174173
set to `true`).
175174
See https://cloud.google.com/endpoint-verification/docs/overview::
176-
175+
177176
try:
178177
default_ssl_credentials = SslCredentials()
179178
except:
@@ -194,21 +193,21 @@ def my_client_cert_callback():
194193
environment variable is not `true`, a regular TLS channel is created;
195194
otherwise, a mutual TLS channel is created, however, the call should be
196195
wrapped in a try/except block in case of malformed context aware metadata.
197-
196+
198197
The following code uses regular_endpoint, it works the same no matter the
199198
created channle is regular or mutual TLS. Regular endpoint ignores client
200199
certificate and key::
201-
200+
202201
channel = google.auth.transport.grpc.secure_authorized_channel(
203202
credentials, request, regular_endpoint)
204-
203+
205204
The following code uses mtls_endpoint, if the created channle is regular,
206205
and API mtls_endpoint is confgured to require client SSL credentials, API
207206
calls using this channel will be rejected::
208-
207+
209208
channel = google.auth.transport.grpc.secure_authorized_channel(
210209
credentials, request, mtls_endpoint)
211-
210+
212211
Args:
213212
credentials (google.auth.credentials.Credentials): The credentials to
214213
add to requests.
@@ -232,10 +231,10 @@ def my_client_cert_callback():
232231
This argument does nothing unless `GOOGLE_API_USE_CLIENT_CERTIFICATE`
233232
environment variable is explicitly set to `true`.
234233
kwargs: Additional arguments to pass to :func:`grpc.secure_channel`.
235-
234+
236235
Returns:
237236
grpc.Channel: The created gRPC channel.
238-
237+
239238
Raises:
240239
google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel
241240
creation failed for any reason.
@@ -245,13 +244,13 @@ def my_client_cert_callback():
245244

246245
# Create a set of grpc.CallCredentials using the metadata plugin.
247246
google_auth_credentials = grpc.metadata_call_credentials(metadata_plugin)
248-
247+
249248
if ssl_credentials and client_cert_callback:
250249
raise exceptions.MalformedError(
251250
"Received both ssl_credentials and client_cert_callback; "
252251
"these are mutually exclusive."
253252
)
254-
253+
255254
# If SSL credentials are not explicitly set, try client_cert_callback and ADC.
256255
cached_cert = None
257256
if not ssl_credentials:
@@ -270,7 +269,7 @@ def my_client_cert_callback():
270269
cached_cert = adc_ssl_credentils._cached_cert
271270
else:
272271
ssl_credentials = grpc.ssl_channel_credentials()
273-
272+
274273
# Combine the ssl credentials and the authorization credentials.
275274
composite_credentials = grpc.composite_channel_credentials(
276275
ssl_credentials, google_auth_credentials
@@ -292,19 +291,19 @@ def my_client_cert_callback():
292291
interceptor = _MTLSCallInterceptor(cached_cert)
293292

294293
wrapper = _MTLSRefreshingChannel(target, factory_args, channel, cached_cert)
295-
294+
296295
interceptor._wrapper = wrapper
297296
return grpc.intercept_channel(wrapper, interceptor)
298297
return channel
299-
298+
300299
class SslCredentials:
301300
"""Class for application default SSL credentials.
302-
301+
303302
The behavior is controlled by `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment
304303
variable whose default value is `false`. Client certificate will not be used
305304
unless the environment variable is explicitly set to `true`. See
306305
https://google.aip.dev/auth/4114
307-
306+
308307
If the environment variable is `true`, then for devices with endpoint verification
309308
support, a device certificate will be automatically loaded and mutual TLS will
310309
be established.
@@ -433,19 +432,3 @@ def stream_stream(self, method, *args, **kwargs): return self._channel.stream_st
433432
def subscribe(self, *args, **kwargs): return self._channel.subscribe(*args, **kwargs)
434433
def unsubscribe(self, *args, **kwargs): return self._channel.unsubscribe(*args, **kwargs)
435434
def close(self): self._channel.close()
436-
437-
438-
439-
440-
441-
442-
443-
444-
445-
446-
447-
448-
449-
450-
451-

0 commit comments

Comments
 (0)