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.
diff --git a/Makefile b/Makefile
index 08f5ba2..b60f22d 100644
--- a/Makefile
+++ b/Makefile
@@ -481,6 +481,7 @@
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 @@
$(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 @@
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/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/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
+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 f8c97e3..3ad8944 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",
@@ -1187,6 +1190,20 @@
]
},
{
+ "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",
"language": "c",
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 472887f..217c194 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -51,7 +51,7 @@
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 d372e69..d2cf09a 100644
--- a/src/core/httpcli/httpcli.c
+++ b/src/core/httpcli/httpcli.c
@@ -216,6 +216,7 @@
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 42d1a90..7e72b23 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -1076,7 +1076,3 @@
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 7b89294..9886afc 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -60,8 +60,15 @@
"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 0000000..9cffd64
--- /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 <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_FILE
+
+#include "src/core/security/credentials.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#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 0000000..a8b7115
--- /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 <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include "src/core/security/credentials.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#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 0000000..d7a974d
--- /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 <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+#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 0000000..b11acac
--- /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 <stdio.h>
+#include <string.h>
+
+#include "src/core/security/credentials.h"
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/cmdline.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/sync.h>
+
+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 37bc9cb..2591a82 100644
--- a/vsprojects/vs2013/Grpc.mak
+++ b/vsprojects/vs2013/Grpc.mak
@@ -450,6 +450,14 @@
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 89c0de3..bdbca92 100644
--- a/vsprojects/vs2013/grpc.vcxproj
+++ b/vsprojects/vs2013/grpc.vcxproj
@@ -201,6 +201,12 @@
</ClCompile>
<ClCompile Include="..\..\src\core\security\credentials.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_posix.c">
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_win32.c">
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\default_credentials.c">
+ </ClCompile>
<ClCompile Include="..\..\src\core\security\factories.c">
</ClCompile>
<ClCompile Include="..\..\src\core\security\json_token.c">
diff --git a/vsprojects/vs2013/grpc.vcxproj.filters b/vsprojects/vs2013/grpc.vcxproj.filters
index a2d9f30..d3dd374 100644
--- a/vsprojects/vs2013/grpc.vcxproj.filters
+++ b/vsprojects/vs2013/grpc.vcxproj.filters
@@ -22,6 +22,15 @@
<ClCompile Include="..\..\src\core\security\credentials.c">
<Filter>src\core\security</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_posix.c">
+ <Filter>src\core\security</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_win32.c">
+ <Filter>src\core\security</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\default_credentials.c">
+ <Filter>src\core\security</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\core\security\factories.c">
<Filter>src\core\security</Filter>
</ClCompile>
diff --git a/vsprojects/vs2013/grpc_shared.vcxproj b/vsprojects/vs2013/grpc_shared.vcxproj
index 81a280d..9655bb9 100644
--- a/vsprojects/vs2013/grpc_shared.vcxproj
+++ b/vsprojects/vs2013/grpc_shared.vcxproj
@@ -205,6 +205,12 @@
</ClCompile>
<ClCompile Include="..\..\src\core\security\credentials.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_posix.c">
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_win32.c">
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\default_credentials.c">
+ </ClCompile>
<ClCompile Include="..\..\src\core\security\factories.c">
</ClCompile>
<ClCompile Include="..\..\src\core\security\json_token.c">
diff --git a/vsprojects/vs2013/grpc_shared.vcxproj.filters b/vsprojects/vs2013/grpc_shared.vcxproj.filters
index a2d9f30..d3dd374 100644
--- a/vsprojects/vs2013/grpc_shared.vcxproj.filters
+++ b/vsprojects/vs2013/grpc_shared.vcxproj.filters
@@ -22,6 +22,15 @@
<ClCompile Include="..\..\src\core\security\credentials.c">
<Filter>src\core\security</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_posix.c">
+ <Filter>src\core\security</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\credentials_win32.c">
+ <Filter>src\core\security</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\core\security\default_credentials.c">
+ <Filter>src\core\security</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\core\security\factories.c">
<Filter>src\core\security</Filter>
</ClCompile>