Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 1 | /* |
| 2 | * |
Craig Tiller | 6169d5f | 2016-03-31 07:46:18 -0700 | [diff] [blame] | 3 | * Copyright 2015, Google Inc. |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 4 | * 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 Boeuf | 8ca294e | 2016-05-02 14:56:30 -0700 | [diff] [blame] | 34 | #include "src/core/lib/security/credentials/credentials.h" |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 35 | |
| 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 Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 42 | #include "src/core/lib/http/httpcli.h" |
| 43 | #include "src/core/lib/http/parser.h" |
Craig Tiller | 8517886 | 2016-05-18 16:09:16 -0700 | [diff] [blame] | 44 | #include "src/core/lib/iomgr/load_file.h" |
David Garcia Quintas | 2a50dfe | 2016-05-31 15:09:12 -0700 | [diff] [blame] | 45 | #include "src/core/lib/iomgr/polling_entity.h" |
Julien Boeuf | 8ca294e | 2016-05-02 14:56:30 -0700 | [diff] [blame] | 46 | #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" |
Craig Tiller | 804ff71 | 2016-05-05 16:25:40 -0700 | [diff] [blame] | 47 | #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 48 | #include "src/core/lib/slice/slice_internal.h" |
Craig Tiller | 0f31080 | 2016-10-26 16:25:56 -0700 | [diff] [blame] | 49 | #include "src/core/lib/slice/slice_string_helpers.h" |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 50 | #include "src/core/lib/support/env.h" |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 51 | #include "src/core/lib/support/string.h" |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 52 | #include "src/core/lib/surface/api_trace.h" |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 53 | |
| 54 | /* -- Constants. -- */ |
| 55 | |
| 56 | #define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 57 | |
| 58 | /* -- Default credentials. -- */ |
| 59 | |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 60 | static grpc_channel_credentials *default_credentials = NULL; |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 61 | static int compute_engine_detection_done = 0; |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 62 | static gpr_mu g_state_mu; |
| 63 | static gpr_mu *g_polling_mu; |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 64 | static gpr_once g_once = GPR_ONCE_INIT; |
| 65 | |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 66 | static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); } |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 67 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 68 | typedef struct { |
David Garcia Quintas | 2a50dfe | 2016-05-31 15:09:12 -0700 | [diff] [blame] | 69 | grpc_polling_entity pollent; |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 70 | int is_done; |
| 71 | int success; |
Craig Tiller | 804ff71 | 2016-05-05 16:25:40 -0700 | [diff] [blame] | 72 | grpc_http_response response; |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 73 | } compute_engine_detector; |
| 74 | |
Craig Tiller | 804ff71 | 2016-05-05 16:25:40 -0700 | [diff] [blame] | 75 | static void on_compute_engine_detection_http_response(grpc_exec_ctx *exec_ctx, |
| 76 | void *user_data, |
| 77 | grpc_error *error) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 78 | compute_engine_detector *detector = (compute_engine_detector *)user_data; |
Craig Tiller | 804ff71 | 2016-05-05 16:25:40 -0700 | [diff] [blame] | 79 | if (error == GRPC_ERROR_NONE && detector->response.status == 200 && |
| 80 | detector->response.hdr_count > 0) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 81 | /* 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 Tiller | 804ff71 | 2016-05-05 16:25:40 -0700 | [diff] [blame] | 84 | for (i = 0; i < detector->response.hdr_count; i++) { |
| 85 | grpc_http_header *header = &detector->response.hdrs[i]; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 86 | if (strcmp(header->key, "Metadata-Flavor") == 0 && |
| 87 | strcmp(header->value, "Google") == 0) { |
| 88 | detector->success = 1; |
| 89 | break; |
| 90 | } |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 91 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 92 | } |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 93 | gpr_mu_lock(g_polling_mu); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 94 | detector->is_done = 1; |
Craig Tiller | c97065d | 2016-06-07 13:00:14 -0700 | [diff] [blame] | 95 | GRPC_LOG_IF_ERROR( |
| 96 | "Pollset kick", |
| 97 | grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent), NULL)); |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 98 | gpr_mu_unlock(g_polling_mu); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 99 | } |
| 100 | |
Craig Tiller | 804ff71 | 2016-05-05 16:25:40 -0700 | [diff] [blame] | 101 | static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *e) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 102 | grpc_pollset_destroy(p); |
Craig Tiller | d1bec03 | 2015-09-18 17:29:00 -0700 | [diff] [blame] | 103 | } |
yang-g | 2109217 | 2015-08-07 15:44:14 -0700 | [diff] [blame] | 104 | |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 105 | static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) { |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 106 | compute_engine_detector detector; |
| 107 | grpc_httpcli_request request; |
Craig Tiller | a0abe37 | 2015-06-01 11:31:08 -0700 | [diff] [blame] | 108 | grpc_httpcli_context context; |
Craig Tiller | d1bec03 | 2015-09-18 17:29:00 -0700 | [diff] [blame] | 109 | grpc_closure destroy_closure; |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 110 | |
| 111 | /* The http call is local. If it takes more than one sec, it is for sure not |
| 112 | on compute engine. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 113 | gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 114 | |
David Garcia Quintas | f72eb97 | 2016-05-03 18:28:09 -0700 | [diff] [blame] | 115 | grpc_pollset *pollset = gpr_malloc(grpc_pollset_size()); |
| 116 | grpc_pollset_init(pollset, &g_polling_mu); |
David Garcia Quintas | c4d5112 | 2016-06-06 14:56:02 -0700 | [diff] [blame] | 117 | detector.pollent = grpc_polling_entity_create_from_pollset(pollset); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 118 | detector.is_done = 0; |
| 119 | detector.success = 0; |
| 120 | |
Craig Tiller | b30d3d7 | 2016-05-18 12:12:21 -0700 | [diff] [blame] | 121 | memset(&detector.response, 0, sizeof(detector.response)); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 122 | memset(&request, 0, sizeof(grpc_httpcli_request)); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 123 | request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST; |
Matthew Iselin | 1824f05 | 2016-02-10 12:16:06 +1100 | [diff] [blame] | 124 | request.http.path = "/"; |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 125 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 126 | grpc_httpcli_context_init(&context); |
Craig Tiller | 00d5b5c | 2015-05-08 10:20:59 -0700 | [diff] [blame] | 127 | |
Craig Tiller | 20afa3d | 2016-10-17 14:52:14 -0700 | [diff] [blame] | 128 | grpc_resource_quota *resource_quota = |
| 129 | grpc_resource_quota_create("google_default_credentials"); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 130 | grpc_httpcli_get( |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 131 | exec_ctx, &context, &detector.pollent, resource_quota, &request, |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 132 | gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay), |
Craig Tiller | 91031da | 2016-12-28 15:44:25 -0800 | [diff] [blame] | 133 | grpc_closure_create(on_compute_engine_detection_http_response, &detector, |
| 134 | grpc_schedule_on_exec_ctx), |
Craig Tiller | 804ff71 | 2016-05-05 16:25:40 -0700 | [diff] [blame] | 135 | &detector.response); |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 136 | grpc_resource_quota_unref_internal(exec_ctx, resource_quota); |
Craig Tiller | d1bec03 | 2015-09-18 17:29:00 -0700 | [diff] [blame] | 137 | |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 138 | grpc_exec_ctx_flush(exec_ctx); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 139 | |
| 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 Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 142 | gpr_mu_lock(g_polling_mu); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 143 | while (!detector.is_done) { |
Craig Tiller | d0a8ae1 | 2016-02-18 08:01:19 -0800 | [diff] [blame] | 144 | grpc_pollset_worker *worker = NULL; |
Craig Tiller | 4f1d0f3 | 2016-05-06 17:12:37 -0700 | [diff] [blame] | 145 | if (!GRPC_LOG_IF_ERROR( |
| 146 | "pollset_work", |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 147 | grpc_pollset_work(exec_ctx, |
Craig Tiller | c97065d | 2016-06-07 13:00:14 -0700 | [diff] [blame] | 148 | grpc_polling_entity_pollset(&detector.pollent), |
| 149 | &worker, gpr_now(GPR_CLOCK_MONOTONIC), |
Craig Tiller | 4f1d0f3 | 2016-05-06 17:12:37 -0700 | [diff] [blame] | 150 | gpr_inf_future(GPR_CLOCK_MONOTONIC)))) { |
| 151 | detector.is_done = 1; |
| 152 | detector.success = 0; |
| 153 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 154 | } |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 155 | gpr_mu_unlock(g_polling_mu); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 156 | |
Craig Tiller | 9e5ac1b | 2017-02-14 22:25:50 -0800 | [diff] [blame] | 157 | grpc_httpcli_context_destroy(exec_ctx, &context); |
David Garcia Quintas | f72eb97 | 2016-05-03 18:28:09 -0700 | [diff] [blame] | 158 | grpc_closure_init(&destroy_closure, destroy_pollset, |
Craig Tiller | 91031da | 2016-12-28 15:44:25 -0800 | [diff] [blame] | 159 | grpc_polling_entity_pollset(&detector.pollent), |
| 160 | grpc_schedule_on_exec_ctx); |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 161 | grpc_pollset_shutdown(exec_ctx, |
David Garcia Quintas | 69ff63d | 2016-06-06 16:39:47 -0700 | [diff] [blame] | 162 | grpc_polling_entity_pollset(&detector.pollent), |
David Garcia Quintas | f72eb97 | 2016-05-03 18:28:09 -0700 | [diff] [blame] | 163 | &destroy_closure); |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 164 | g_polling_mu = NULL; |
Craig Tiller | a9cc625 | 2016-11-30 14:10:51 -0800 | [diff] [blame] | 165 | grpc_exec_ctx_flush(exec_ctx); |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 166 | |
David Garcia Quintas | c4d5112 | 2016-06-06 14:56:02 -0700 | [diff] [blame] | 167 | gpr_free(grpc_polling_entity_pollset(&detector.pollent)); |
Craig Tiller | b30d3d7 | 2016-05-18 12:12:21 -0700 | [diff] [blame] | 168 | grpc_http_response_destroy(&detector.response); |
Craig Tiller | a8be91b | 2016-02-19 16:22:44 -0800 | [diff] [blame] | 169 | |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 170 | return detector.success; |
| 171 | } |
| 172 | |
| 173 | /* Takes ownership of creds_path if not NULL. */ |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 174 | static grpc_error *create_default_creds_from_path( |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 175 | grpc_exec_ctx *exec_ctx, char *creds_path, grpc_call_credentials **creds) { |
Julien Boeuf | 5400606 | 2015-07-07 19:13:04 -0700 | [diff] [blame] | 176 | grpc_json *json = NULL; |
| 177 | grpc_auth_json_key key; |
| 178 | grpc_auth_refresh_token token; |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 179 | grpc_call_credentials *result = NULL; |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 180 | grpc_slice creds_data = grpc_empty_slice(); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 181 | grpc_error *error = GRPC_ERROR_NONE; |
| 182 | if (creds_path == NULL) { |
| 183 | error = GRPC_ERROR_CREATE("creds_path unset"); |
| 184 | goto end; |
| 185 | } |
Craig Tiller | 8517886 | 2016-05-18 16:09:16 -0700 | [diff] [blame] | 186 | error = grpc_load_file(creds_path, 0, &creds_data); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 187 | if (error != GRPC_ERROR_NONE) { |
| 188 | goto end; |
| 189 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 190 | json = grpc_json_parse_string_with_len( |
Craig Tiller | 618e67d | 2016-10-26 21:08:10 -0700 | [diff] [blame] | 191 | (char *)GRPC_SLICE_START_PTR(creds_data), GRPC_SLICE_LENGTH(creds_data)); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 192 | if (json == NULL) { |
Craig Tiller | 0f31080 | 2016-10-26 16:25:56 -0700 | [diff] [blame] | 193 | char *dump = grpc_dump_slice(creds_data, GPR_DUMP_HEX | GPR_DUMP_ASCII); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 194 | 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 Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 199 | |
Julien Boeuf | 5400606 | 2015-07-07 19:13:04 -0700 | [diff] [blame] | 200 | /* First, try an auth json key. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 201 | 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 Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 205 | exec_ctx, key, grpc_max_auth_token_lifetime()); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 206 | if (result == NULL) { |
| 207 | error = GRPC_ERROR_CREATE( |
| 208 | "grpc_service_account_jwt_access_credentials_create_from_auth_json_" |
| 209 | "key failed"); |
| 210 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 211 | goto end; |
| 212 | } |
Julien Boeuf | 5400606 | 2015-07-07 19:13:04 -0700 | [diff] [blame] | 213 | |
| 214 | /* Then try a refresh token if the auth json key was invalid. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 215 | 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 Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 219 | if (result == NULL) { |
| 220 | error = GRPC_ERROR_CREATE( |
| 221 | "grpc_refresh_token_credentials_create_from_auth_refresh_token " |
| 222 | "failed"); |
| 223 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 224 | goto end; |
| 225 | } |
Julien Boeuf | 5400606 | 2015-07-07 19:13:04 -0700 | [diff] [blame] | 226 | |
| 227 | end: |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 228 | GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 229 | if (creds_path != NULL) gpr_free(creds_path); |
Craig Tiller | a59c16c | 2016-10-31 07:25:01 -0700 | [diff] [blame] | 230 | grpc_slice_unref_internal(exec_ctx, creds_data); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 231 | if (json != NULL) grpc_json_destroy(json); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 232 | *creds = result; |
| 233 | return error; |
Julien Boeuf | 9835cf0 | 2015-03-09 16:56:44 -0700 | [diff] [blame] | 234 | } |
| 235 | |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 236 | grpc_channel_credentials *grpc_google_default_credentials_create(void) { |
| 237 | grpc_channel_credentials *result = NULL; |
| 238 | grpc_call_credentials *call_creds = NULL; |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 239 | grpc_error *error = GRPC_ERROR_CREATE("Failed to create Google credentials"); |
| 240 | grpc_error *err; |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 241 | grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
Masood Malekghassemi | 76c3d74 | 2015-08-19 18:22:53 -0700 | [diff] [blame] | 242 | |
| 243 | GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); |
| 244 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 245 | gpr_once_init(&g_once, init_default_credentials); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 246 | |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 247 | gpr_mu_lock(&g_state_mu); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 248 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 249 | if (default_credentials != NULL) { |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 250 | result = grpc_channel_credentials_ref(default_credentials); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 251 | goto end; |
| 252 | } |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 253 | |
| 254 | /* First, try the environment variable. */ |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 255 | err = create_default_creds_from_path( |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 256 | &exec_ctx, gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 257 | if (err == GRPC_ERROR_NONE) goto end; |
| 258 | error = grpc_error_add_child(error, err); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 259 | |
| 260 | /* Then the well-known file. */ |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 261 | err = create_default_creds_from_path( |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 262 | &exec_ctx, grpc_get_well_known_google_credentials_file_path(), |
| 263 | &call_creds); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 264 | if (err == GRPC_ERROR_NONE) goto end; |
| 265 | error = grpc_error_add_child(error, err); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 266 | |
| 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 Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 269 | if (!compute_engine_detection_done) { |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 270 | int need_compute_engine_creds = |
| 271 | is_stack_running_on_compute_engine(&exec_ctx); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 272 | compute_engine_detection_done = 1; |
| 273 | if (need_compute_engine_creds) { |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 274 | call_creds = grpc_google_compute_engine_credentials_create(NULL); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 275 | if (call_creds == NULL) { |
| 276 | error = grpc_error_add_child( |
| 277 | error, GRPC_ERROR_CREATE("Failed to get credentials from network")); |
| 278 | } |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 279 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 280 | } |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 281 | |
| 282 | end: |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 283 | if (result == NULL) { |
| 284 | if (call_creds != NULL) { |
Craig Tiller | b113649 | 2015-11-18 11:30:17 -0800 | [diff] [blame] | 285 | /* Blend with default ssl credentials and add a global reference so that |
| 286 | it |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 287 | 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 Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 294 | grpc_channel_credentials_unref(&exec_ctx, ssl_creds); |
| 295 | grpc_call_credentials_unref(&exec_ctx, call_creds); |
Julien Boeuf | 441176d | 2015-10-09 21:14:07 -0700 | [diff] [blame] | 296 | result = default_credentials; |
| 297 | } else { |
| 298 | gpr_log(GPR_ERROR, "Could not create google default credentials."); |
| 299 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 300 | } |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 301 | gpr_mu_unlock(&g_state_mu); |
Craig Tiller | 4727b9b | 2016-05-17 17:19:19 -0700 | [diff] [blame] | 302 | if (result == NULL) { |
| 303 | GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error); |
| 304 | } else { |
| 305 | GRPC_ERROR_UNREF(error); |
| 306 | } |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 307 | grpc_exec_ctx_finish(&exec_ctx); |
Julien Boeuf | cd9b1c8 | 2015-02-20 17:40:41 -0800 | [diff] [blame] | 308 | return result; |
| 309 | } |
Julien Boeuf | b037bb6 | 2015-07-08 14:58:14 -0700 | [diff] [blame] | 310 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 311 | void grpc_flush_cached_google_default_credentials(void) { |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 312 | grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 313 | gpr_once_init(&g_once, init_default_credentials); |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 314 | gpr_mu_lock(&g_state_mu); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 315 | if (default_credentials != NULL) { |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 316 | grpc_channel_credentials_unref(&exec_ctx, default_credentials); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 317 | default_credentials = NULL; |
| 318 | } |
Julien Boeuf | 2408a1c | 2015-12-09 22:33:41 -0800 | [diff] [blame] | 319 | compute_engine_detection_done = 0; |
Craig Tiller | 69b093b | 2016-02-25 19:04:07 -0800 | [diff] [blame] | 320 | gpr_mu_unlock(&g_state_mu); |
Craig Tiller | bd1795c | 2016-10-31 15:30:00 -0700 | [diff] [blame] | 321 | grpc_exec_ctx_finish(&exec_ctx); |
Julien Boeuf | b037bb6 | 2015-07-08 14:58:14 -0700 | [diff] [blame] | 322 | } |
Julien Boeuf | 2408a1c | 2015-12-09 22:33:41 -0800 | [diff] [blame] | 323 | |
| 324 | /* -- Well known credentials path. -- */ |
| 325 | |
| 326 | static grpc_well_known_credentials_path_getter creds_path_getter = NULL; |
| 327 | |
| 328 | char *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 | |
| 333 | void grpc_override_well_known_credentials_path_getter( |
| 334 | grpc_well_known_credentials_path_getter getter) { |
| 335 | creds_path_getter = getter; |
| 336 | } |