From cd9b1c850db35ad37669dc0a650712b1cd29527f Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Fri, 20 Feb 2015 17:40:41 -0800 Subject: [PATCH] Added support for default credentials. - Tested with new tool (print_default_creds_token) on: - workstation for env var and well known place. - GCE for compute engine default creds. - I'd prefer the grpc_default_credentials_create() API to remain synchronous even though there may be an async call for gce detection on which we block. --- Makefile | 43 +++- build.json | 17 ++ include/grpc/grpc_security.h | 2 +- src/core/httpcli/httpcli.c | 1 + src/core/security/credentials.c | 4 - src/core/security/credentials.h | 7 + src/core/security/credentials_posix.c | 60 ++++++ src/core/security/credentials_win32.c | 60 ++++++ src/core/security/default_credentials.c | 185 ++++++++++++++++++ .../core/security/print_default_creds_token.c | 107 ++++++++++ vsprojects/vs2013/Grpc.mak | 8 + vsprojects/vs2013/grpc.vcxproj | 6 + vsprojects/vs2013/grpc.vcxproj.filters | 9 + vsprojects/vs2013/grpc_shared.vcxproj | 6 + vsprojects/vs2013/grpc_shared.vcxproj.filters | 9 + 15 files changed, 518 insertions(+), 6 deletions(-) create mode 100644 src/core/security/credentials_posix.c create mode 100644 src/core/security/credentials_win32.c create mode 100644 src/core/security/default_credentials.c create mode 100644 test/core/security/print_default_creds_token.c diff --git a/Makefile b/Makefile index 08f5ba26721..b60f22de2c9 100644 --- a/Makefile +++ b/Makefile @@ -481,6 +481,7 @@ grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test +grpc_print_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_default_creds_token grpc_stream_op_test: $(BINDIR)/$(CONFIG)/grpc_stream_op_test hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test @@ -1763,7 +1764,7 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/thread_pool_test || ( echo test thread_pool_test failed ; exit 1 ) -tools: privatelibs $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 +tools: privatelibs $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 $(BINDIR)/$(CONFIG)/grpc_print_default_creds_token buildbenchmarks: privatelibs $(BINDIR)/$(CONFIG)/grpc_completion_queue_benchmark $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark @@ -2283,6 +2284,9 @@ LIBGRPC_SRC = \ src/core/security/auth.c \ src/core/security/base64.c \ src/core/security/credentials.c \ + src/core/security/credentials_posix.c \ + src/core/security/credentials_win32.c \ + src/core/security/default_credentials.c \ src/core/security/factories.c \ src/core/security/json_token.c \ src/core/security/secure_endpoint.c \ @@ -2424,6 +2428,9 @@ src/core/httpcli/parser.c: $(OPENSSL_DEP) src/core/security/auth.c: $(OPENSSL_DEP) src/core/security/base64.c: $(OPENSSL_DEP) src/core/security/credentials.c: $(OPENSSL_DEP) +src/core/security/credentials_posix.c: $(OPENSSL_DEP) +src/core/security/credentials_win32.c: $(OPENSSL_DEP) +src/core/security/default_credentials.c: $(OPENSSL_DEP) src/core/security/factories.c: $(OPENSSL_DEP) src/core/security/json_token.c: $(OPENSSL_DEP) src/core/security/secure_endpoint.c: $(OPENSSL_DEP) @@ -2582,6 +2589,9 @@ $(OBJDIR)/$(CONFIG)/src/core/httpcli/parser.o: $(OBJDIR)/$(CONFIG)/src/core/security/auth.o: $(OBJDIR)/$(CONFIG)/src/core/security/base64.o: $(OBJDIR)/$(CONFIG)/src/core/security/credentials.o: +$(OBJDIR)/$(CONFIG)/src/core/security/credentials_posix.o: +$(OBJDIR)/$(CONFIG)/src/core/security/credentials_win32.o: +$(OBJDIR)/$(CONFIG)/src/core/security/default_credentials.o: $(OBJDIR)/$(CONFIG)/src/core/security/factories.o: $(OBJDIR)/$(CONFIG)/src/core/security/json_token.o: $(OBJDIR)/$(CONFIG)/src/core/security/secure_endpoint.o: @@ -6546,6 +6556,37 @@ endif endif +GRPC_PRINT_DEFAULT_CREDS_TOKEN_SRC = \ + test/core/security/print_default_creds_token.c \ + +GRPC_PRINT_DEFAULT_CREDS_TOKEN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_PRINT_DEFAULT_CREDS_TOKEN_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/grpc_print_default_creds_token: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpc_print_default_creds_token: $(GRPC_PRINT_DEFAULT_CREDS_TOKEN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(GRPC_PRINT_DEFAULT_CREDS_TOKEN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_print_default_creds_token + +endif + +$(OBJDIR)/$(CONFIG)/test/core/security/print_default_creds_token.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpc_print_default_creds_token: $(GRPC_PRINT_DEFAULT_CREDS_TOKEN_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPC_PRINT_DEFAULT_CREDS_TOKEN_OBJS:.o=.dep) +endif +endif + + GRPC_STREAM_OP_TEST_SRC = \ test/core/transport/stream_op_test.c \ diff --git a/build.json b/build.json index f8c97e3437d..3ad89449a7e 100644 --- a/build.json +++ b/build.json @@ -320,6 +320,9 @@ "src/core/security/auth.c", "src/core/security/base64.c", "src/core/security/credentials.c", + "src/core/security/credentials_posix.c", + "src/core/security/credentials_win32.c", + "src/core/security/default_credentials.c", "src/core/security/factories.c", "src/core/security/json_token.c", "src/core/security/secure_endpoint.c", @@ -1186,6 +1189,20 @@ "gpr" ] }, + { + "name": "grpc_print_default_creds_token", + "build": "tool", + "language": "c", + "src": [ + "test/core/security/print_default_creds_token.c" + ], + "deps": [ + "grpc_test_util", + "grpc", + "gpr_test_util", + "gpr" + ] + }, { "name": "grpc_stream_op_test", "build": "test", diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 472887f7c6b..217c1940ac7 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -51,7 +51,7 @@ typedef struct grpc_credentials grpc_credentials; The creator of the credentials object is responsible for its release. */ void grpc_credentials_release(grpc_credentials *creds); -/* Creates default credentials. */ +/* Creates default credentials to connect to a google gRPC service. */ grpc_credentials *grpc_default_credentials_create(void); /* Environment variable that points to the default SSL roots file. This file diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index d372e694e96..d2cf09a8df4 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -216,6 +216,7 @@ static void on_resolved(void *arg, grpc_resolved_addresses *addresses) { gpr_log(GPR_DEBUG, "%s", __FUNCTION__); if (!addresses) { finish(req, 0); + return; } req->addresses = addresses; req->next_address = 0; diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 42d1a900fc5..7e72b238c80 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -1076,7 +1076,3 @@ grpc_credentials *grpc_iam_credentials_create(const char *token, c->md_ctx, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector); return &c->base; } - -/* -- Default credentials TODO(jboeuf). -- */ - -grpc_credentials *grpc_default_credentials_create(void) { return NULL; } diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h index 7b8929492b2..9886afc9c0a 100644 --- a/src/core/security/credentials.h +++ b/src/core/security/credentials.h @@ -60,8 +60,15 @@ typedef enum { "x-goog-iam-authorization-token" #define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector" +#define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud" +#define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \ + "application_default_credentials.json" + /* --- grpc_credentials. --- */ +/* It is the caller's responsibility to gpr_free the result if not NULL. */ +char *grpc_get_well_known_credentials_file_path(void); + typedef void (*grpc_credentials_metadata_cb)(void *user_data, grpc_mdelem **md_elems, size_t num_md, diff --git a/src/core/security/credentials_posix.c b/src/core/security/credentials_posix.c new file mode 100644 index 00000000000..9cffd64d31c --- /dev/null +++ b/src/core/security/credentials_posix.c @@ -0,0 +1,60 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#ifdef GPR_POSIX_FILE + +#include "src/core/security/credentials.h" + +#include +#include + +#include "src/core/support/env.h" +#include "src/core/support/string.h" + +char *grpc_get_well_known_credentials_file_path(void) { + char *result = NULL; + char *home = gpr_getenv("HOME"); + if (home == NULL) { + gpr_log(GPR_ERROR, "Could not get HOME environment variable."); + return NULL; + } + gpr_asprintf(&result, "%s/.config/%s/%s", home, + GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY, + GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE); + gpr_free(home); + return result; +} + +#endif /* GPR_POSIX_FILE */ diff --git a/src/core/security/credentials_win32.c b/src/core/security/credentials_win32.c new file mode 100644 index 00000000000..a8b711517b9 --- /dev/null +++ b/src/core/security/credentials_win32.c @@ -0,0 +1,60 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#ifdef GPR_WIN32 + +#include "src/core/security/credentials.h" + +#include +#include + +#include "src/core/support/env.h" +#include "src/core/support/string.h" + +char *grpc_get_well_known_credentials_file_path(void) { + char *result = NULL; + char *appdata_path = gpr_getenv("APPDATA"); + if (appdata_path == NULL) { + gpr_log(GPR_ERROR, "Could not get APPDATA environment variable."); + return NULL; + } + gpr_asprintf(&result, "%s/%s/%s", appdata_path, + GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY, + GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE); + gpr_free(appdata_path); + return result; +} + +#endif /* GPR_WIN32 */ diff --git a/src/core/security/default_credentials.c b/src/core/security/default_credentials.c new file mode 100644 index 00000000000..d7a974d8a16 --- /dev/null +++ b/src/core/security/default_credentials.c @@ -0,0 +1,185 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/security/credentials.h" + +#include + +#include +#include +#include + +#include "src/core/httpcli/httpcli.h" +#include "src/core/support/env.h" +#include "src/core/support/file.h" + +/* -- Constants. -- */ + +#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" +#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS" + +/* -- Default credentials. -- */ + +static grpc_credentials *default_credentials = NULL; +static int compute_engine_detection_done = 0; +static gpr_mu g_mu; +static gpr_once g_once = GPR_ONCE_INIT; + +static void init_default_credentials(void) { + gpr_mu_init(&g_mu); +} + +typedef struct { + gpr_cv cv; + gpr_mu mu; + int is_done; + int success; +} compute_engine_detector; + +static void on_compute_engine_detection_http_response( + void *user_data, const grpc_httpcli_response *response) { + compute_engine_detector *detector = (compute_engine_detector *)user_data; + if (response != NULL && response->status == 200 && response->hdr_count > 0) { + /* Internet providers can return a generic response to all requests, so + it is necessary to check that metadata header is present also. */ + size_t i; + for (i = 0; i < response->hdr_count; i++) { + grpc_httpcli_header *header = &response->hdrs[i]; + if (!strcmp(header->key, "Metadata-Flavor") && + !strcmp(header->value, "Google")) { + detector->success = 1; + break; + } + } + } + gpr_mu_lock(&detector->mu); + detector->is_done = 1; + gpr_mu_unlock(&detector->mu); + gpr_cv_signal(&detector->cv); +} + +static int is_stack_running_on_compute_engine(void) { + compute_engine_detector detector; + grpc_httpcli_request request; + + /* The http call is local. If it takes more than one sec, it is for sure not + on compute engine. */ + gpr_timespec max_detection_delay = {1, 0}; + + gpr_mu_init(&detector.mu); + gpr_cv_init(&detector.cv); + detector.is_done = 0; + detector.success = 0; + + memset(&request, 0, sizeof(grpc_httpcli_request)); + request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST; + request.path = "/"; + + grpc_httpcli_get(&request, gpr_time_add(gpr_now(), max_detection_delay), + on_compute_engine_detection_http_response, &detector); + + /* Block until we get the response. This is not ideal but this should only be + called once for the lifetime of the process by the default credentials. */ + gpr_mu_lock(&detector.mu); + while (!detector.is_done) { + gpr_cv_wait(&detector.cv, &detector.mu, gpr_inf_future); + } + gpr_mu_unlock(&detector.mu); + + gpr_mu_destroy(&detector.mu); + gpr_cv_destroy(&detector.cv); + return detector.success; +} + +/* Takes ownership of creds_path if not NULL. */ +static grpc_credentials *create_jwt_creds_from_path(char *creds_path) { + grpc_credentials *result = NULL; + gpr_slice creds_data; + int file_ok = 0; + if (creds_path == NULL) return NULL; + creds_data = gpr_load_file(creds_path, &file_ok); + gpr_free(creds_path); + if (file_ok) { + result = grpc_jwt_credentials_create( + (const char *)GPR_SLICE_START_PTR(creds_data), + grpc_max_auth_token_lifetime); + gpr_slice_unref(creds_data); + } + return result; +} + +grpc_credentials *grpc_default_credentials_create(void) { + grpc_credentials *result = NULL; + int serving_cached_credentials = 0; + gpr_once_init(&g_once, init_default_credentials); + + gpr_mu_lock(&g_mu); + + if (default_credentials != NULL) { + result = default_credentials; + serving_cached_credentials = 1; + goto end; + } + + /* First, try the environment variable. */ + result = + create_jwt_creds_from_path(gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR)); + if (result != NULL) goto end; + + /* Then the well-known file. */ + result = create_jwt_creds_from_path( + grpc_get_well_known_credentials_file_path()); + if (result != NULL) goto end; + + /* At last try to see if we're on compute engine (do the detection only once + since it requires a network test). */ + if (!compute_engine_detection_done) { + int need_compute_engine_creds = is_stack_running_on_compute_engine(); + compute_engine_detection_done = 1; + if (need_compute_engine_creds) { + result = grpc_compute_engine_credentials_create(); + } + } + +end: + if (!serving_cached_credentials && result != NULL) { + /* Blend with default ssl credentials and add a global reference so that it + can be cached and re-served. */ + result = grpc_composite_credentials_create( + grpc_ssl_credentials_create(NULL, NULL), result); + GPR_ASSERT(result != NULL); + default_credentials = grpc_credentials_ref(result); + } + gpr_mu_unlock(&g_mu); + return result; +} diff --git a/test/core/security/print_default_creds_token.c b/test/core/security/print_default_creds_token.c new file mode 100644 index 00000000000..b11acace40a --- /dev/null +++ b/test/core/security/print_default_creds_token.c @@ -0,0 +1,107 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "src/core/security/credentials.h" +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + gpr_cv cv; + gpr_mu mu; + int is_done; +} synchronizer; + +static void on_metadata_response(void *user_data, grpc_mdelem **md_elems, + size_t num_md, + grpc_credentials_status status) { + synchronizer *sync = user_data; + if (status == GRPC_CREDENTIALS_ERROR) { + fprintf(stderr, "Fetching token failed.\n"); + } else { + GPR_ASSERT(num_md == 1); + printf("\nGot token: %s\n\n", + (const char *)GPR_SLICE_START_PTR(md_elems[0]->value->slice)); + } + gpr_mu_lock(&sync->mu); + sync->is_done = 1; + gpr_mu_unlock(&sync->mu); + gpr_cv_signal(&sync->cv); +} + +int main(int argc, char **argv) { + int result = 0; + synchronizer sync; + grpc_credentials *creds = NULL; + char *service_url = "https://test.foo.google.com/Foo"; + gpr_cmdline *cl = gpr_cmdline_create("print_default_creds_token"); + gpr_cmdline_add_string(cl, "service_url", + "Service URL for the token request.", + &service_url); + gpr_cmdline_parse(cl, argc, argv); + + grpc_init(); + + creds = grpc_default_credentials_create(); + if (creds == NULL) { + fprintf(stderr, "\nCould not find default credentials.\n\n"); + result = 1; + goto end; + } + + gpr_mu_init(&sync.mu); + gpr_cv_init(&sync.cv); + sync.is_done = 0; + + grpc_credentials_get_request_metadata(creds, "", on_metadata_response, &sync); + + gpr_mu_lock(&sync.mu); + while (!sync.is_done) gpr_cv_wait(&sync.cv, &sync.mu, gpr_inf_future); + gpr_mu_unlock(&sync.mu); + + gpr_mu_destroy(&sync.mu); + gpr_cv_destroy(&sync.cv); + grpc_credentials_release(creds); + +end: + gpr_cmdline_destroy(cl); + grpc_shutdown(); + return result; +} diff --git a/vsprojects/vs2013/Grpc.mak b/vsprojects/vs2013/Grpc.mak index 37bc9cb3310..2591a82321f 100644 --- a/vsprojects/vs2013/Grpc.mak +++ b/vsprojects/vs2013/Grpc.mak @@ -450,6 +450,14 @@ grpc_json_token_test: grpc_json_token_test.exe echo Running grpc_json_token_test $(OUT_DIR)\grpc_json_token_test.exe +grpc_print_default_creds_token.exe: grpc_test_util + echo Building grpc_print_default_creds_token + $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ ..\..\test\core\security\print_default_creds_token.c + $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\grpc_print_default_creds_token.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\print_default_creds_token.obj +grpc_print_default_creds_token: grpc_print_default_creds_token.exe + echo Running grpc_print_default_creds_token + $(OUT_DIR)\grpc_print_default_creds_token.exe + grpc_stream_op_test.exe: grpc_test_util echo Building grpc_stream_op_test $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ ..\..\test\core\transport\stream_op_test.c diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index 89c0de333c9..bdbca9222d1 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -201,6 +201,12 @@ + + + + + + diff --git a/vsprojects/vs2013/grpc.vcxproj.filters b/vsprojects/vs2013/grpc.vcxproj.filters index a2d9f30eda7..d3dd374eb6a 100644 --- a/vsprojects/vs2013/grpc.vcxproj.filters +++ b/vsprojects/vs2013/grpc.vcxproj.filters @@ -22,6 +22,15 @@ src\core\security + + src\core\security + + + src\core\security + + + src\core\security + src\core\security diff --git a/vsprojects/vs2013/grpc_shared.vcxproj b/vsprojects/vs2013/grpc_shared.vcxproj index 81a280d912a..9655bb90b5b 100644 --- a/vsprojects/vs2013/grpc_shared.vcxproj +++ b/vsprojects/vs2013/grpc_shared.vcxproj @@ -205,6 +205,12 @@ + + + + + + diff --git a/vsprojects/vs2013/grpc_shared.vcxproj.filters b/vsprojects/vs2013/grpc_shared.vcxproj.filters index a2d9f30eda7..d3dd374eb6a 100644 --- a/vsprojects/vs2013/grpc_shared.vcxproj.filters +++ b/vsprojects/vs2013/grpc_shared.vcxproj.filters @@ -22,6 +22,15 @@ src\core\security + + src\core\security + + + src\core\security + + + src\core\security + src\core\security