1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include "src/core/lib/security/credentials/credentials.h" 22 23 #include <string.h> 24 25 #include <grpc/support/alloc.h> 26 #include <grpc/support/log.h> 27 #include <grpc/support/sync.h> 28 29 #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" 30 #include "src/core/lib/channel/channel_args.h" 31 #include "src/core/lib/gpr/env.h" 32 #include "src/core/lib/gpr/string.h" 33 #include "src/core/lib/http/httpcli.h" 34 #include "src/core/lib/http/parser.h" 35 #include "src/core/lib/iomgr/load_file.h" 36 #include "src/core/lib/iomgr/polling_entity.h" 37 #include "src/core/lib/security/credentials/alts/alts_credentials.h" 38 #include "src/core/lib/security/credentials/alts/check_gcp_environment.h" 39 #include "src/core/lib/security/credentials/google_default/google_default_credentials.h" 40 #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" 41 #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" 42 #include "src/core/lib/slice/slice_internal.h" 43 #include "src/core/lib/slice/slice_string_helpers.h" 44 #include "src/core/lib/surface/api_trace.h" 45 46 /* -- Constants. -- */ 47 48 #define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" 49 50 /* -- Default credentials. -- */ 51 52 static grpc_channel_credentials* g_default_credentials = nullptr; 53 static int g_compute_engine_detection_done = 0; 54 static gpr_mu g_state_mu; 55 static gpr_once g_once = GPR_ONCE_INIT; 56 static grpc_core::internal::grpc_gce_tenancy_checker g_gce_tenancy_checker = 57 grpc_alts_is_running_on_gcp; 58 59 static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); } 60 61 typedef struct { 62 grpc_polling_entity pollent; 63 int is_done; 64 int success; 65 grpc_http_response response; 66 } compute_engine_detector; 67 68 static void google_default_credentials_destruct( 69 grpc_channel_credentials* creds) { 70 grpc_google_default_channel_credentials* c = 71 reinterpret_cast<grpc_google_default_channel_credentials*>(creds); 72 grpc_channel_credentials_unref(c->alts_creds); 73 grpc_channel_credentials_unref(c->ssl_creds); 74 } 75 76 static grpc_security_status google_default_create_security_connector( 77 grpc_channel_credentials* creds, grpc_call_credentials* call_creds, 78 const char* target, const grpc_channel_args* args, 79 grpc_channel_security_connector** sc, grpc_channel_args** new_args) { 80 grpc_google_default_channel_credentials* c = 81 reinterpret_cast<grpc_google_default_channel_credentials*>(creds); 82 bool is_grpclb_load_balancer = grpc_channel_arg_get_bool( 83 grpc_channel_args_find(args, GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 84 false); 85 bool is_backend_from_grpclb_load_balancer = grpc_channel_arg_get_bool( 86 grpc_channel_args_find( 87 args, GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER), 88 false); 89 bool use_alts = 90 is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer; 91 grpc_security_status status = GRPC_SECURITY_ERROR; 92 status = use_alts ? c->alts_creds->vtable->create_security_connector( 93 c->alts_creds, call_creds, target, args, sc, new_args) 94 : c->ssl_creds->vtable->create_security_connector( 95 c->ssl_creds, call_creds, target, args, sc, new_args); 96 /* grpclb-specific channel args are removed from the channel args set 97 * to ensure backends and fallback adresses will have the same set of channel 98 * args. By doing that, it guarantees the connections to backends will not be 99 * torn down and re-connected when switching in and out of fallback mode. 100 */ 101 if (use_alts) { 102 static const char* args_to_remove[] = { 103 GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER, 104 GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER, 105 }; 106 *new_args = grpc_channel_args_copy_and_add_and_remove( 107 args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), nullptr, 0); 108 } 109 return status; 110 } 111 112 static grpc_channel_credentials_vtable google_default_credentials_vtable = { 113 google_default_credentials_destruct, 114 google_default_create_security_connector, nullptr}; 115 116 /* Takes ownership of creds_path if not NULL. */ 117 static grpc_error* create_default_creds_from_path( 118 char* creds_path, grpc_call_credentials** creds) { 119 grpc_json* json = nullptr; 120 grpc_auth_json_key key; 121 grpc_auth_refresh_token token; 122 grpc_call_credentials* result = nullptr; 123 grpc_slice creds_data = grpc_empty_slice(); 124 grpc_error* error = GRPC_ERROR_NONE; 125 if (creds_path == nullptr) { 126 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("creds_path unset"); 127 goto end; 128 } 129 error = grpc_load_file(creds_path, 0, &creds_data); 130 if (error != GRPC_ERROR_NONE) { 131 goto end; 132 } 133 json = grpc_json_parse_string_with_len( 134 reinterpret_cast<char*> GRPC_SLICE_START_PTR(creds_data), 135 GRPC_SLICE_LENGTH(creds_data)); 136 if (json == nullptr) { 137 error = grpc_error_set_str( 138 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse JSON"), 139 GRPC_ERROR_STR_RAW_BYTES, grpc_slice_ref_internal(creds_data)); 140 goto end; 141 } 142 143 /* First, try an auth json key. */ 144 key = grpc_auth_json_key_create_from_json(json); 145 if (grpc_auth_json_key_is_valid(&key)) { 146 result = 147 grpc_service_account_jwt_access_credentials_create_from_auth_json_key( 148 key, grpc_max_auth_token_lifetime()); 149 if (result == nullptr) { 150 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( 151 "grpc_service_account_jwt_access_credentials_create_from_auth_json_" 152 "key failed"); 153 } 154 goto end; 155 } 156 157 /* Then try a refresh token if the auth json key was invalid. */ 158 token = grpc_auth_refresh_token_create_from_json(json); 159 if (grpc_auth_refresh_token_is_valid(&token)) { 160 result = 161 grpc_refresh_token_credentials_create_from_auth_refresh_token(token); 162 if (result == nullptr) { 163 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( 164 "grpc_refresh_token_credentials_create_from_auth_refresh_token " 165 "failed"); 166 } 167 goto end; 168 } 169 170 end: 171 GPR_ASSERT((result == nullptr) + (error == GRPC_ERROR_NONE) == 1); 172 if (creds_path != nullptr) gpr_free(creds_path); 173 grpc_slice_unref_internal(creds_data); 174 if (json != nullptr) grpc_json_destroy(json); 175 *creds = result; 176 return error; 177 } 178 179 grpc_channel_credentials* grpc_google_default_credentials_create(void) { 180 grpc_channel_credentials* result = nullptr; 181 grpc_call_credentials* call_creds = nullptr; 182 grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( 183 "Failed to create Google credentials"); 184 grpc_error* err; 185 grpc_core::ExecCtx exec_ctx; 186 187 GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); 188 189 gpr_once_init(&g_once, init_default_credentials); 190 191 gpr_mu_lock(&g_state_mu); 192 193 if (g_default_credentials != nullptr) { 194 result = grpc_channel_credentials_ref(g_default_credentials); 195 goto end; 196 } 197 198 /* First, try the environment variable. */ 199 err = create_default_creds_from_path( 200 gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds); 201 if (err == GRPC_ERROR_NONE) goto end; 202 error = grpc_error_add_child(error, err); 203 204 /* Then the well-known file. */ 205 err = create_default_creds_from_path( 206 grpc_get_well_known_google_credentials_file_path(), &call_creds); 207 if (err == GRPC_ERROR_NONE) goto end; 208 error = grpc_error_add_child(error, err); 209 210 /* At last try to see if we're on compute engine (do the detection only once 211 since it requires a network test). */ 212 if (!g_compute_engine_detection_done) { 213 int need_compute_engine_creds = g_gce_tenancy_checker(); 214 g_compute_engine_detection_done = 1; 215 if (need_compute_engine_creds) { 216 call_creds = grpc_google_compute_engine_credentials_create(nullptr); 217 if (call_creds == nullptr) { 218 error = grpc_error_add_child( 219 error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( 220 "Failed to get credentials from network")); 221 } 222 } 223 } 224 225 end: 226 if (result == nullptr) { 227 if (call_creds != nullptr) { 228 /* Create google default credentials. */ 229 auto creds = static_cast<grpc_google_default_channel_credentials*>( 230 gpr_zalloc(sizeof(grpc_google_default_channel_credentials))); 231 creds->base.vtable = &google_default_credentials_vtable; 232 creds->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT; 233 gpr_ref_init(&creds->base.refcount, 1); 234 creds->ssl_creds = 235 grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); 236 GPR_ASSERT(creds->ssl_creds != nullptr); 237 grpc_alts_credentials_options* options = 238 grpc_alts_credentials_client_options_create(); 239 creds->alts_creds = grpc_alts_credentials_create(options); 240 grpc_alts_credentials_options_destroy(options); 241 /* Add a global reference so that it can be cached and re-served. */ 242 g_default_credentials = grpc_composite_channel_credentials_create( 243 &creds->base, call_creds, nullptr); 244 GPR_ASSERT(g_default_credentials != nullptr); 245 grpc_channel_credentials_unref(&creds->base); 246 grpc_call_credentials_unref(call_creds); 247 result = grpc_channel_credentials_ref(g_default_credentials); 248 } else { 249 gpr_log(GPR_ERROR, "Could not create google default credentials."); 250 } 251 } 252 gpr_mu_unlock(&g_state_mu); 253 if (result == nullptr) { 254 GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error); 255 } else { 256 GRPC_ERROR_UNREF(error); 257 } 258 259 return result; 260 } 261 262 namespace grpc_core { 263 namespace internal { 264 265 void set_gce_tenancy_checker_for_testing(grpc_gce_tenancy_checker checker) { 266 g_gce_tenancy_checker = checker; 267 } 268 269 } // namespace internal 270 } // namespace grpc_core 271 272 void grpc_flush_cached_google_default_credentials(void) { 273 grpc_core::ExecCtx exec_ctx; 274 gpr_once_init(&g_once, init_default_credentials); 275 gpr_mu_lock(&g_state_mu); 276 if (g_default_credentials != nullptr) { 277 grpc_channel_credentials_unref(g_default_credentials); 278 g_default_credentials = nullptr; 279 } 280 g_compute_engine_detection_done = 0; 281 gpr_mu_unlock(&g_state_mu); 282 } 283 284 /* -- Well known credentials path. -- */ 285 286 static grpc_well_known_credentials_path_getter creds_path_getter = nullptr; 287 288 char* grpc_get_well_known_google_credentials_file_path(void) { 289 if (creds_path_getter != nullptr) return creds_path_getter(); 290 return grpc_get_well_known_google_credentials_file_path_impl(); 291 } 292 293 void grpc_override_well_known_credentials_path_getter( 294 grpc_well_known_credentials_path_getter getter) { 295 creds_path_getter = getter; 296 } 297