diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h index 6d45895e77e..3cd652cd574 100644 --- a/src/core/security/credentials.h +++ b/src/core/security/credentials.h @@ -93,6 +93,14 @@ typedef enum { /* It is the caller's responsibility to gpr_free the result if not NULL. */ char *grpc_get_well_known_google_credentials_file_path(void); +/* Implementation function for the different platforms. */ +char *grpc_get_well_known_google_credentials_file_path_impl(void); + +/* Override for testing only. Not thread-safe */ +typedef char *(*grpc_well_known_credentials_path_getter)(void); +void grpc_override_well_known_credentials_path_getter( + grpc_well_known_credentials_path_getter getter); + /* --- grpc_channel_credentials. --- */ typedef struct { @@ -201,6 +209,7 @@ grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( const struct grpc_httpcli_response *response, grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime); + void grpc_flush_cached_google_default_credentials(void); /* Metadata-only credentials with the specified key and value where diff --git a/src/core/security/credentials_posix.c b/src/core/security/credentials_posix.c index 20f67a7f149..0c92bd4a96b 100644 --- a/src/core/security/credentials_posix.c +++ b/src/core/security/credentials_posix.c @@ -44,7 +44,7 @@ #include "src/core/support/env.h" #include "src/core/support/string.h" -char *grpc_get_well_known_google_credentials_file_path(void) { +char *grpc_get_well_known_google_credentials_file_path_impl(void) { char *result = NULL; char *home = gpr_getenv("HOME"); if (home == NULL) { diff --git a/src/core/security/credentials_win32.c b/src/core/security/credentials_win32.c index 92dfd9bdfe6..8ee9f706a1f 100644 --- a/src/core/security/credentials_win32.c +++ b/src/core/security/credentials_win32.c @@ -44,7 +44,7 @@ #include "src/core/support/env.h" #include "src/core/support/string.h" -char *grpc_get_well_known_google_credentials_file_path(void) { +char *grpc_get_well_known_google_credentials_file_path_impl(void) { char *result = NULL; char *appdata_path = gpr_getenv("APPDATA"); if (appdata_path == NULL) { diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c index 6a54fe4e47c..5385e41130f 100644 --- a/src/core/security/google_default_credentials.c +++ b/src/core/security/google_default_credentials.c @@ -241,5 +241,20 @@ void grpc_flush_cached_google_default_credentials(void) { grpc_channel_credentials_unref(default_credentials); default_credentials = NULL; } + compute_engine_detection_done = 0; gpr_mu_unlock(&g_mu); } + +/* -- Well known credentials path. -- */ + +static grpc_well_known_credentials_path_getter creds_path_getter = NULL; + +char *grpc_get_well_known_google_credentials_file_path(void) { + if (creds_path_getter != NULL) return creds_path_getter(); + return grpc_get_well_known_google_credentials_file_path_impl(); +} + +void grpc_override_well_known_credentials_path_getter( + grpc_well_known_credentials_path_getter getter) { + creds_path_getter = getter; +} diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 834113488c9..d6febf586ea 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -878,7 +878,7 @@ static void test_google_default_creds_auth_key(void) { gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ } -static void test_google_default_creds_access_token(void) { +static void test_google_default_creds_refresh_token(void) { grpc_google_refresh_token_credentials *refresh; grpc_composite_channel_credentials *creds; grpc_flush_cached_google_default_credentials(); @@ -894,6 +894,60 @@ static void test_google_default_creds_access_token(void) { gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ } +static int default_creds_gce_detection_httpcli_get_success_override( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + gpr_timespec deadline, grpc_httpcli_response_cb on_response, + void *user_data) { + grpc_httpcli_response response = http_response(200, ""); + grpc_httpcli_header header; + header.key = "Metadata-Flavor"; + header.value = "Google"; + response.hdr_count = 1; + response.hdrs = &header; + GPR_ASSERT(strcmp(request->path, "/") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + on_response(exec_ctx, user_data, &response); + return 1; +} + +static char *null_well_known_creds_path_getter(void) { + return NULL; +} + +static void test_google_default_creds_gce(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_composite_channel_credentials *creds; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + grpc_flush_cached_google_default_credentials(); + gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ + grpc_override_well_known_credentials_path_getter( + null_well_known_creds_path_getter); + + /* Simulate a successful detection of GCE. */ + grpc_httpcli_set_override( + default_creds_gce_detection_httpcli_get_success_override, + httpcli_post_should_not_be_called); + creds = (grpc_composite_channel_credentials *) + grpc_google_default_credentials_create(); + + /* Verify that the default creds actually embeds a GCE creds. */ + GPR_ASSERT(creds != NULL); + GPR_ASSERT(creds->call_creds != NULL); + grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, + httpcli_post_should_not_be_called); + grpc_call_credentials_get_request_metadata( + &exec_ctx, creds->call_creds, NULL, auth_md_ctx, + on_oauth2_creds_get_metadata_success, (void *)test_user_data); + grpc_exec_ctx_flush(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); + + /* Cleanup. */ + grpc_channel_credentials_release(&creds->base); + grpc_httpcli_set_override(NULL, NULL); + grpc_override_well_known_credentials_path_getter(NULL); +} + typedef enum { PLUGIN_INITIAL_STATE, PLUGIN_GET_METADATA_CALLED_STATE, @@ -1067,7 +1121,8 @@ int main(int argc, char **argv) { test_jwt_creds_success(); test_jwt_creds_signing_failure(); test_google_default_creds_auth_key(); - test_google_default_creds_access_token(); + test_google_default_creds_refresh_token(); + test_google_default_creds_gce(); test_metadata_plugin_success(); test_metadata_plugin_failure(); test_get_well_known_google_credentials_file_path();