blob: ecd26de9faa15dbb43ed69aeb6f21b9a7f18df0e [file] [log] [blame]
Julien Boeufcd9b1c82015-02-20 17:40:41 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Julien Boeufcd9b1c82015-02-20 17:40:41 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Julien Boeuf8ca294e2016-05-02 14:56:30 -070034#include "src/core/lib/security/credentials/credentials.h"
Julien Boeufcd9b1c82015-02-20 17:40:41 -080035
36#include <string.h>
37
38#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
40#include <grpc/support/sync.h>
41
Craig Tiller9533d042016-03-25 17:11:06 -070042#include "src/core/lib/http/httpcli.h"
43#include "src/core/lib/http/parser.h"
Craig Tiller85178862016-05-18 16:09:16 -070044#include "src/core/lib/iomgr/load_file.h"
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070045#include "src/core/lib/iomgr/polling_entity.h"
Julien Boeuf8ca294e2016-05-02 14:56:30 -070046#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
Craig Tiller804ff712016-05-05 16:25:40 -070047#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
Craig Tillerbd1795c2016-10-31 15:30:00 -070048#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -070049#include "src/core/lib/slice/slice_string_helpers.h"
Craig Tiller9533d042016-03-25 17:11:06 -070050#include "src/core/lib/support/env.h"
Craig Tiller4727b9b2016-05-17 17:19:19 -070051#include "src/core/lib/support/string.h"
Craig Tiller9533d042016-03-25 17:11:06 -070052#include "src/core/lib/surface/api_trace.h"
Julien Boeufcd9b1c82015-02-20 17:40:41 -080053
54/* -- Constants. -- */
55
56#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal"
Julien Boeufcd9b1c82015-02-20 17:40:41 -080057
58/* -- Default credentials. -- */
59
Julien Boeuf441176d2015-10-09 21:14:07 -070060static grpc_channel_credentials *default_credentials = NULL;
Julien Boeufcd9b1c82015-02-20 17:40:41 -080061static int compute_engine_detection_done = 0;
Craig Tiller69b093b2016-02-25 19:04:07 -080062static gpr_mu g_state_mu;
63static gpr_mu *g_polling_mu;
Julien Boeufcd9b1c82015-02-20 17:40:41 -080064static gpr_once g_once = GPR_ONCE_INIT;
65
Craig Tiller69b093b2016-02-25 19:04:07 -080066static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); }
Julien Boeufcd9b1c82015-02-20 17:40:41 -080067
Craig Tillera82950e2015-09-22 12:33:20 -070068typedef struct {
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070069 grpc_polling_entity pollent;
Julien Boeufcd9b1c82015-02-20 17:40:41 -080070 int is_done;
71 int success;
Craig Tiller804ff712016-05-05 16:25:40 -070072 grpc_http_response response;
Julien Boeufcd9b1c82015-02-20 17:40:41 -080073} compute_engine_detector;
74
Craig Tiller804ff712016-05-05 16:25:40 -070075static void on_compute_engine_detection_http_response(grpc_exec_ctx *exec_ctx,
76 void *user_data,
77 grpc_error *error) {
Craig Tillera82950e2015-09-22 12:33:20 -070078 compute_engine_detector *detector = (compute_engine_detector *)user_data;
Craig Tiller804ff712016-05-05 16:25:40 -070079 if (error == GRPC_ERROR_NONE && detector->response.status == 200 &&
80 detector->response.hdr_count > 0) {
Craig Tillera82950e2015-09-22 12:33:20 -070081 /* Internet providers can return a generic response to all requests, so
82 it is necessary to check that metadata header is present also. */
83 size_t i;
Craig Tiller804ff712016-05-05 16:25:40 -070084 for (i = 0; i < detector->response.hdr_count; i++) {
85 grpc_http_header *header = &detector->response.hdrs[i];
Craig Tillera82950e2015-09-22 12:33:20 -070086 if (strcmp(header->key, "Metadata-Flavor") == 0 &&
87 strcmp(header->value, "Google") == 0) {
88 detector->success = 1;
89 break;
90 }
Julien Boeufcd9b1c82015-02-20 17:40:41 -080091 }
Craig Tillera82950e2015-09-22 12:33:20 -070092 }
Craig Tiller69b093b2016-02-25 19:04:07 -080093 gpr_mu_lock(g_polling_mu);
Julien Boeufcd9b1c82015-02-20 17:40:41 -080094 detector->is_done = 1;
Craig Tillerc97065d2016-06-07 13:00:14 -070095 GRPC_LOG_IF_ERROR(
96 "Pollset kick",
97 grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent), NULL));
Craig Tiller69b093b2016-02-25 19:04:07 -080098 gpr_mu_unlock(g_polling_mu);
Julien Boeufcd9b1c82015-02-20 17:40:41 -080099}
100
Craig Tiller804ff712016-05-05 16:25:40 -0700101static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *e) {
Craig Tillera82950e2015-09-22 12:33:20 -0700102 grpc_pollset_destroy(p);
Craig Tillerd1bec032015-09-18 17:29:00 -0700103}
yang-g21092172015-08-07 15:44:14 -0700104
Craig Tillerbd1795c2016-10-31 15:30:00 -0700105static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) {
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800106 compute_engine_detector detector;
107 grpc_httpcli_request request;
Craig Tillera0abe372015-06-01 11:31:08 -0700108 grpc_httpcli_context context;
Craig Tillerd1bec032015-09-18 17:29:00 -0700109 grpc_closure destroy_closure;
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800110
111 /* The http call is local. If it takes more than one sec, it is for sure not
112 on compute engine. */
Craig Tillera82950e2015-09-22 12:33:20 -0700113 gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800114
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700115 grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
116 grpc_pollset_init(pollset, &g_polling_mu);
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700117 detector.pollent = grpc_polling_entity_create_from_pollset(pollset);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800118 detector.is_done = 0;
119 detector.success = 0;
120
Craig Tillerb30d3d72016-05-18 12:12:21 -0700121 memset(&detector.response, 0, sizeof(detector.response));
Craig Tillera82950e2015-09-22 12:33:20 -0700122 memset(&request, 0, sizeof(grpc_httpcli_request));
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800123 request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
Matthew Iselin1824f052016-02-10 12:16:06 +1100124 request.http.path = "/";
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800125
Craig Tillera82950e2015-09-22 12:33:20 -0700126 grpc_httpcli_context_init(&context);
Craig Tiller00d5b5c2015-05-08 10:20:59 -0700127
Craig Tiller20afa3d2016-10-17 14:52:14 -0700128 grpc_resource_quota *resource_quota =
129 grpc_resource_quota_create("google_default_credentials");
Craig Tillera82950e2015-09-22 12:33:20 -0700130 grpc_httpcli_get(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700131 exec_ctx, &context, &detector.pollent, resource_quota, &request,
Craig Tillera82950e2015-09-22 12:33:20 -0700132 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
Craig Tiller91031da2016-12-28 15:44:25 -0800133 grpc_closure_create(on_compute_engine_detection_http_response, &detector,
134 grpc_schedule_on_exec_ctx),
Craig Tiller804ff712016-05-05 16:25:40 -0700135 &detector.response);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700136 grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
Craig Tillerd1bec032015-09-18 17:29:00 -0700137
Craig Tillerbd1795c2016-10-31 15:30:00 -0700138 grpc_exec_ctx_flush(exec_ctx);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800139
140 /* Block until we get the response. This is not ideal but this should only be
141 called once for the lifetime of the process by the default credentials. */
Craig Tiller69b093b2016-02-25 19:04:07 -0800142 gpr_mu_lock(g_polling_mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700143 while (!detector.is_done) {
Craig Tillerd0a8ae12016-02-18 08:01:19 -0800144 grpc_pollset_worker *worker = NULL;
Craig Tiller4f1d0f32016-05-06 17:12:37 -0700145 if (!GRPC_LOG_IF_ERROR(
146 "pollset_work",
Craig Tillerbd1795c2016-10-31 15:30:00 -0700147 grpc_pollset_work(exec_ctx,
Craig Tillerc97065d2016-06-07 13:00:14 -0700148 grpc_polling_entity_pollset(&detector.pollent),
149 &worker, gpr_now(GPR_CLOCK_MONOTONIC),
Craig Tiller4f1d0f32016-05-06 17:12:37 -0700150 gpr_inf_future(GPR_CLOCK_MONOTONIC)))) {
151 detector.is_done = 1;
152 detector.success = 0;
153 }
Craig Tillera82950e2015-09-22 12:33:20 -0700154 }
Craig Tiller69b093b2016-02-25 19:04:07 -0800155 gpr_mu_unlock(g_polling_mu);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800156
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800157 grpc_httpcli_context_destroy(exec_ctx, &context);
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700158 grpc_closure_init(&destroy_closure, destroy_pollset,
Craig Tiller91031da2016-12-28 15:44:25 -0800159 grpc_polling_entity_pollset(&detector.pollent),
160 grpc_schedule_on_exec_ctx);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700161 grpc_pollset_shutdown(exec_ctx,
David Garcia Quintas69ff63d2016-06-06 16:39:47 -0700162 grpc_polling_entity_pollset(&detector.pollent),
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700163 &destroy_closure);
Craig Tiller69b093b2016-02-25 19:04:07 -0800164 g_polling_mu = NULL;
Craig Tillera9cc6252016-11-30 14:10:51 -0800165 grpc_exec_ctx_flush(exec_ctx);
Craig Tiller69b093b2016-02-25 19:04:07 -0800166
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700167 gpr_free(grpc_polling_entity_pollset(&detector.pollent));
Craig Tillerb30d3d72016-05-18 12:12:21 -0700168 grpc_http_response_destroy(&detector.response);
Craig Tillera8be91b2016-02-19 16:22:44 -0800169
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800170 return detector.success;
171}
172
173/* Takes ownership of creds_path if not NULL. */
Craig Tiller4727b9b2016-05-17 17:19:19 -0700174static grpc_error *create_default_creds_from_path(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700175 grpc_exec_ctx *exec_ctx, char *creds_path, grpc_call_credentials **creds) {
Julien Boeuf54006062015-07-07 19:13:04 -0700176 grpc_json *json = NULL;
177 grpc_auth_json_key key;
178 grpc_auth_refresh_token token;
Julien Boeuf441176d2015-10-09 21:14:07 -0700179 grpc_call_credentials *result = NULL;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800180 grpc_slice creds_data = grpc_empty_slice();
Craig Tiller4727b9b2016-05-17 17:19:19 -0700181 grpc_error *error = GRPC_ERROR_NONE;
182 if (creds_path == NULL) {
183 error = GRPC_ERROR_CREATE("creds_path unset");
184 goto end;
185 }
Craig Tiller85178862016-05-18 16:09:16 -0700186 error = grpc_load_file(creds_path, 0, &creds_data);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700187 if (error != GRPC_ERROR_NONE) {
188 goto end;
189 }
Craig Tillera82950e2015-09-22 12:33:20 -0700190 json = grpc_json_parse_string_with_len(
Craig Tiller618e67d2016-10-26 21:08:10 -0700191 (char *)GRPC_SLICE_START_PTR(creds_data), GRPC_SLICE_LENGTH(creds_data));
Craig Tiller4727b9b2016-05-17 17:19:19 -0700192 if (json == NULL) {
Craig Tiller0f310802016-10-26 16:25:56 -0700193 char *dump = grpc_dump_slice(creds_data, GPR_DUMP_HEX | GPR_DUMP_ASCII);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700194 error = grpc_error_set_str(GRPC_ERROR_CREATE("Failed to parse JSON"),
195 GRPC_ERROR_STR_RAW_BYTES, dump);
196 gpr_free(dump);
197 goto end;
198 }
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800199
Julien Boeuf54006062015-07-07 19:13:04 -0700200 /* First, try an auth json key. */
Craig Tillera82950e2015-09-22 12:33:20 -0700201 key = grpc_auth_json_key_create_from_json(json);
202 if (grpc_auth_json_key_is_valid(&key)) {
203 result =
204 grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700205 exec_ctx, key, grpc_max_auth_token_lifetime());
Craig Tiller4727b9b2016-05-17 17:19:19 -0700206 if (result == NULL) {
207 error = GRPC_ERROR_CREATE(
208 "grpc_service_account_jwt_access_credentials_create_from_auth_json_"
209 "key failed");
210 }
Craig Tillera82950e2015-09-22 12:33:20 -0700211 goto end;
212 }
Julien Boeuf54006062015-07-07 19:13:04 -0700213
214 /* Then try a refresh token if the auth json key was invalid. */
Craig Tillera82950e2015-09-22 12:33:20 -0700215 token = grpc_auth_refresh_token_create_from_json(json);
216 if (grpc_auth_refresh_token_is_valid(&token)) {
217 result =
218 grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700219 if (result == NULL) {
220 error = GRPC_ERROR_CREATE(
221 "grpc_refresh_token_credentials_create_from_auth_refresh_token "
222 "failed");
223 }
Craig Tillera82950e2015-09-22 12:33:20 -0700224 goto end;
225 }
Julien Boeuf54006062015-07-07 19:13:04 -0700226
227end:
Craig Tiller4727b9b2016-05-17 17:19:19 -0700228 GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700229 if (creds_path != NULL) gpr_free(creds_path);
Craig Tillera59c16c2016-10-31 07:25:01 -0700230 grpc_slice_unref_internal(exec_ctx, creds_data);
Craig Tillera82950e2015-09-22 12:33:20 -0700231 if (json != NULL) grpc_json_destroy(json);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700232 *creds = result;
233 return error;
Julien Boeuf9835cf02015-03-09 16:56:44 -0700234}
235
Julien Boeuf441176d2015-10-09 21:14:07 -0700236grpc_channel_credentials *grpc_google_default_credentials_create(void) {
237 grpc_channel_credentials *result = NULL;
238 grpc_call_credentials *call_creds = NULL;
Craig Tiller4727b9b2016-05-17 17:19:19 -0700239 grpc_error *error = GRPC_ERROR_CREATE("Failed to create Google credentials");
240 grpc_error *err;
Craig Tillerbd1795c2016-10-31 15:30:00 -0700241 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700242
243 GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
244
Craig Tillera82950e2015-09-22 12:33:20 -0700245 gpr_once_init(&g_once, init_default_credentials);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800246
Craig Tiller69b093b2016-02-25 19:04:07 -0800247 gpr_mu_lock(&g_state_mu);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800248
Craig Tillera82950e2015-09-22 12:33:20 -0700249 if (default_credentials != NULL) {
Julien Boeuf441176d2015-10-09 21:14:07 -0700250 result = grpc_channel_credentials_ref(default_credentials);
Craig Tillera82950e2015-09-22 12:33:20 -0700251 goto end;
252 }
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800253
254 /* First, try the environment variable. */
Craig Tiller4727b9b2016-05-17 17:19:19 -0700255 err = create_default_creds_from_path(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700256 &exec_ctx, gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700257 if (err == GRPC_ERROR_NONE) goto end;
258 error = grpc_error_add_child(error, err);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800259
260 /* Then the well-known file. */
Craig Tiller4727b9b2016-05-17 17:19:19 -0700261 err = create_default_creds_from_path(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700262 &exec_ctx, grpc_get_well_known_google_credentials_file_path(),
263 &call_creds);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700264 if (err == GRPC_ERROR_NONE) goto end;
265 error = grpc_error_add_child(error, err);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800266
267 /* At last try to see if we're on compute engine (do the detection only once
268 since it requires a network test). */
Craig Tillera82950e2015-09-22 12:33:20 -0700269 if (!compute_engine_detection_done) {
Craig Tillerbd1795c2016-10-31 15:30:00 -0700270 int need_compute_engine_creds =
271 is_stack_running_on_compute_engine(&exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700272 compute_engine_detection_done = 1;
273 if (need_compute_engine_creds) {
Julien Boeuf441176d2015-10-09 21:14:07 -0700274 call_creds = grpc_google_compute_engine_credentials_create(NULL);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700275 if (call_creds == NULL) {
276 error = grpc_error_add_child(
277 error, GRPC_ERROR_CREATE("Failed to get credentials from network"));
278 }
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800279 }
Craig Tillera82950e2015-09-22 12:33:20 -0700280 }
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800281
282end:
Julien Boeuf441176d2015-10-09 21:14:07 -0700283 if (result == NULL) {
284 if (call_creds != NULL) {
Craig Tillerb1136492015-11-18 11:30:17 -0800285 /* Blend with default ssl credentials and add a global reference so that
286 it
Julien Boeuf441176d2015-10-09 21:14:07 -0700287 can be cached and re-served. */
288 grpc_channel_credentials *ssl_creds =
289 grpc_ssl_credentials_create(NULL, NULL, NULL);
290 default_credentials = grpc_channel_credentials_ref(
291 grpc_composite_channel_credentials_create(ssl_creds, call_creds,
292 NULL));
293 GPR_ASSERT(default_credentials != NULL);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700294 grpc_channel_credentials_unref(&exec_ctx, ssl_creds);
295 grpc_call_credentials_unref(&exec_ctx, call_creds);
Julien Boeuf441176d2015-10-09 21:14:07 -0700296 result = default_credentials;
297 } else {
298 gpr_log(GPR_ERROR, "Could not create google default credentials.");
299 }
Craig Tillera82950e2015-09-22 12:33:20 -0700300 }
Craig Tiller69b093b2016-02-25 19:04:07 -0800301 gpr_mu_unlock(&g_state_mu);
Craig Tiller4727b9b2016-05-17 17:19:19 -0700302 if (result == NULL) {
303 GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error);
304 } else {
305 GRPC_ERROR_UNREF(error);
306 }
Craig Tillerbd1795c2016-10-31 15:30:00 -0700307 grpc_exec_ctx_finish(&exec_ctx);
Julien Boeufcd9b1c82015-02-20 17:40:41 -0800308 return result;
309}
Julien Boeufb037bb62015-07-08 14:58:14 -0700310
Craig Tillera82950e2015-09-22 12:33:20 -0700311void grpc_flush_cached_google_default_credentials(void) {
Craig Tillerbd1795c2016-10-31 15:30:00 -0700312 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillera82950e2015-09-22 12:33:20 -0700313 gpr_once_init(&g_once, init_default_credentials);
Craig Tiller69b093b2016-02-25 19:04:07 -0800314 gpr_mu_lock(&g_state_mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700315 if (default_credentials != NULL) {
Craig Tillerbd1795c2016-10-31 15:30:00 -0700316 grpc_channel_credentials_unref(&exec_ctx, default_credentials);
Craig Tillera82950e2015-09-22 12:33:20 -0700317 default_credentials = NULL;
318 }
Julien Boeuf2408a1c2015-12-09 22:33:41 -0800319 compute_engine_detection_done = 0;
Craig Tiller69b093b2016-02-25 19:04:07 -0800320 gpr_mu_unlock(&g_state_mu);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700321 grpc_exec_ctx_finish(&exec_ctx);
Julien Boeufb037bb62015-07-08 14:58:14 -0700322}
Julien Boeuf2408a1c2015-12-09 22:33:41 -0800323
324/* -- Well known credentials path. -- */
325
326static grpc_well_known_credentials_path_getter creds_path_getter = NULL;
327
328char *grpc_get_well_known_google_credentials_file_path(void) {
329 if (creds_path_getter != NULL) return creds_path_getter();
330 return grpc_get_well_known_google_credentials_file_path_impl();
331}
332
333void grpc_override_well_known_credentials_path_getter(
334 grpc_well_known_credentials_path_getter getter) {
335 creds_path_getter = getter;
336}