Merge pull request #2366 from nicolasnoble/upport-python
Update Python version numbers
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 8e8a896..37d66c0 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -51,6 +51,11 @@
The creator of the credentials object is responsible for its release. */
void grpc_credentials_release(grpc_credentials *creds);
+/* Environment variable that points to the google default application
+ credentials json key or refresh token. Used in the
+ grpc_google_default_credentials_create function. */
+#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
+
/* Creates default credentials to connect to a google gRPC service.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. */
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 8d694c2..52fd5a2 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -41,7 +41,6 @@
#include "src/core/json/json.h"
#include "src/core/httpcli/httpcli.h"
#include "src/core/iomgr/iomgr.h"
-#include "src/core/security/json_token.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
@@ -52,12 +51,12 @@
/* -- Common. -- */
-typedef struct {
+struct grpc_credentials_metadata_request {
grpc_credentials *creds;
grpc_credentials_metadata_cb cb;
grpc_iomgr_closure *on_simulated_token_fetch_done_closure;
void *user_data;
-} grpc_credentials_metadata_request;
+};
static grpc_credentials_metadata_request *
grpc_credentials_metadata_request_create(grpc_credentials *creds,
@@ -152,16 +151,6 @@
/* -- Ssl credentials. -- */
-typedef struct {
- grpc_credentials base;
- grpc_ssl_config config;
-} grpc_ssl_credentials;
-
-typedef struct {
- grpc_server_credentials base;
- grpc_ssl_server_config config;
-} grpc_ssl_server_credentials;
-
static void ssl_destroy(grpc_credentials *creds) {
grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
@@ -326,22 +315,6 @@
/* -- Jwt credentials -- */
-typedef struct {
- grpc_credentials base;
-
- /* Have a simple cache for now with just 1 entry. We could have a map based on
- the service_url for a more sophisticated one. */
- gpr_mu cache_mu;
- struct {
- grpc_credentials_md_store *jwt_md;
- char *service_url;
- gpr_timespec jwt_expiration;
- } cached;
-
- grpc_auth_json_key key;
- gpr_timespec jwt_lifetime;
-} grpc_jwt_credentials;
-
static void jwt_reset_cache(grpc_jwt_credentials *c) {
if (c->cached.jwt_md != NULL) {
grpc_credentials_md_store_unref(c->cached.jwt_md);
@@ -424,10 +397,9 @@
jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata, NULL};
-grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
- gpr_timespec token_lifetime) {
+grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
+ grpc_auth_json_key key, gpr_timespec token_lifetime) {
grpc_jwt_credentials *c;
- grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key);
if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return NULL;
@@ -444,26 +416,14 @@
return &c->base;
}
+grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
+ gpr_timespec token_lifetime) {
+ return grpc_jwt_credentials_create_from_auth_json_key(
+ grpc_auth_json_key_create_from_string(json_key), token_lifetime);
+}
+
/* -- Oauth2TokenFetcher credentials -- */
-/* This object is a base for credentials that need to acquire an oauth2 token
- from an http service. */
-
-typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
- grpc_httpcli_context *http_context,
- grpc_pollset *pollset,
- grpc_httpcli_response_cb response_cb,
- gpr_timespec deadline);
-
-typedef struct {
- grpc_credentials base;
- gpr_mu mu;
- grpc_credentials_md_store *access_token_md;
- gpr_timespec token_expiration;
- grpc_httpcli_context httpcli_context;
- grpc_fetch_oauth2_func fetch_func;
-} grpc_oauth2_token_fetcher_credentials;
-
static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
@@ -669,13 +629,6 @@
/* -- ServiceAccount credentials. -- */
-typedef struct {
- grpc_oauth2_token_fetcher_credentials base;
- grpc_auth_json_key key;
- char *scope;
- gpr_timespec token_lifetime;
-} grpc_service_account_credentials;
-
static void service_account_destroy(grpc_credentials *creds) {
grpc_service_account_credentials *c =
(grpc_service_account_credentials *)creds;
@@ -746,11 +699,6 @@
/* -- RefreshToken credentials. -- */
-typedef struct {
- grpc_oauth2_token_fetcher_credentials base;
- grpc_auth_refresh_token refresh_token;
-} grpc_refresh_token_credentials;
-
static void refresh_token_destroy(grpc_credentials *creds) {
grpc_refresh_token_credentials *c = (grpc_refresh_token_credentials *)creds;
grpc_auth_refresh_token_destruct(&c->refresh_token);
@@ -786,12 +734,9 @@
gpr_free(body);
}
-grpc_credentials *grpc_refresh_token_credentials_create(
- const char *json_refresh_token) {
+grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
+ grpc_auth_refresh_token refresh_token) {
grpc_refresh_token_credentials *c;
- grpc_auth_refresh_token refresh_token =
- grpc_auth_refresh_token_create_from_string(json_refresh_token);
-
if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
return NULL;
@@ -804,13 +749,13 @@
return &c->base.base;
}
-/* -- Fake Oauth2 credentials. -- */
+grpc_credentials *grpc_refresh_token_credentials_create(
+ const char *json_refresh_token) {
+ return grpc_refresh_token_credentials_create_from_auth_refresh_token(
+ grpc_auth_refresh_token_create_from_string(json_refresh_token));
+}
-typedef struct {
- grpc_credentials base;
- grpc_credentials_md_store *access_token_md;
- int is_async;
-} grpc_fake_oauth2_credentials;
+/* -- Fake Oauth2 credentials. -- */
static void fake_oauth2_destroy(grpc_credentials *creds) {
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
@@ -877,11 +822,6 @@
/* -- Oauth2 Access Token credentials. -- */
-typedef struct {
- grpc_credentials base;
- grpc_credentials_md_store *access_token_md;
-} grpc_access_token_credentials;
-
static void access_token_destroy(grpc_credentials *creds) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
grpc_credentials_md_store_unref(c->access_token_md);
@@ -997,12 +937,6 @@
/* -- Composite credentials. -- */
typedef struct {
- grpc_credentials base;
- grpc_credentials_array inner;
- grpc_credentials *connector_creds;
-} grpc_composite_credentials;
-
-typedef struct {
grpc_composite_credentials *composite_creds;
size_t creds_index;
grpc_credentials_md_store *md_elems;
@@ -1232,11 +1166,6 @@
/* -- IAM credentials. -- */
-typedef struct {
- grpc_credentials base;
- grpc_credentials_md_store *iam_md;
-} grpc_iam_credentials;
-
static void iam_destroy(grpc_credentials *creds) {
grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
grpc_credentials_md_store_unref(c->iam_md);
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 75af73a..d988901 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -39,6 +39,8 @@
#include <grpc/grpc_security.h>
#include <grpc/support/sync.h>
+#include "src/core/httpcli/httpcli.h"
+#include "src/core/security/json_token.h"
#include "src/core/security/security_connector.h"
struct grpc_httpcli_response;
@@ -178,11 +180,22 @@
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);
/* Simulates an oauth2 token fetch with the specified value for testing. */
grpc_credentials *grpc_fake_oauth2_credentials_create(
const char *token_md_value, int is_async);
+/* Private constructor for jwt credentials from an already parsed json key.
+ Takes ownership of the key. */
+grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
+ grpc_auth_json_key key, gpr_timespec token_lifetime);
+
+/* Private constructor for refresh token credentials from an already parsed
+ refresh token. Takes ownership of the refresh token. */
+grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
+ grpc_auth_refresh_token token);
+
/* --- grpc_server_credentials. --- */
typedef struct {
@@ -199,4 +212,103 @@
grpc_security_status grpc_server_credentials_create_security_connector(
grpc_server_credentials *creds, grpc_security_connector **sc);
+/* -- Ssl credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_ssl_config config;
+} grpc_ssl_credentials;
+
+typedef struct {
+ grpc_server_credentials base;
+ grpc_ssl_server_config config;
+} grpc_ssl_server_credentials;
+
+/* -- Jwt credentials -- */
+
+typedef struct {
+ grpc_credentials base;
+
+ /* Have a simple cache for now with just 1 entry. We could have a map based on
+ the service_url for a more sophisticated one. */
+ gpr_mu cache_mu;
+ struct {
+ grpc_credentials_md_store *jwt_md;
+ char *service_url;
+ gpr_timespec jwt_expiration;
+ } cached;
+
+ grpc_auth_json_key key;
+ gpr_timespec jwt_lifetime;
+} grpc_jwt_credentials;
+
+/* -- Oauth2TokenFetcher credentials --
+
+ This object is a base for credentials that need to acquire an oauth2 token
+ from an http service. */
+
+typedef struct grpc_credentials_metadata_request
+ grpc_credentials_metadata_request;
+
+typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
+ grpc_httpcli_context *http_context,
+ grpc_pollset *pollset,
+ grpc_httpcli_response_cb response_cb,
+ gpr_timespec deadline);
+
+typedef struct {
+ grpc_credentials base;
+ gpr_mu mu;
+ grpc_credentials_md_store *access_token_md;
+ gpr_timespec token_expiration;
+ grpc_httpcli_context httpcli_context;
+ grpc_fetch_oauth2_func fetch_func;
+} grpc_oauth2_token_fetcher_credentials;
+
+/* -- ServiceAccount credentials. -- */
+
+typedef struct {
+ grpc_oauth2_token_fetcher_credentials base;
+ grpc_auth_json_key key;
+ char *scope;
+ gpr_timespec token_lifetime;
+} grpc_service_account_credentials;
+
+/* -- RefreshToken credentials. -- */
+
+typedef struct {
+ grpc_oauth2_token_fetcher_credentials base;
+ grpc_auth_refresh_token refresh_token;
+} grpc_refresh_token_credentials;
+
+/* -- Oauth2 Access Token credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_md_store *access_token_md;
+} grpc_access_token_credentials;
+
+/* -- Fake Oauth2 credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_md_store *access_token_md;
+ int is_async;
+} grpc_fake_oauth2_credentials;
+
+/* -- IAM credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_md_store *iam_md;
+} grpc_iam_credentials;
+
+/* -- Composite credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_credentials_array inner;
+ grpc_credentials *connector_creds;
+} grpc_composite_credentials;
+
#endif /* GRPC_INTERNAL_CORE_SECURITY_CREDENTIALS_H */
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index 5822ce6..cd92f9d 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -46,7 +46,6 @@
/* -- Constants. -- */
#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal"
-#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
/* -- Default credentials. -- */
@@ -123,36 +122,40 @@
}
/* Takes ownership of creds_path if not NULL. */
-static grpc_credentials *create_jwt_creds_from_path(char *creds_path) {
+static grpc_credentials *create_default_creds_from_path(char *creds_path) {
+ grpc_json *json = NULL;
+ grpc_auth_json_key key;
+ grpc_auth_refresh_token token;
grpc_credentials *result = NULL;
- gpr_slice creds_data;
+ gpr_slice creds_data = gpr_empty_slice();
int file_ok = 0;
- if (creds_path == NULL) return NULL;
- creds_data = gpr_load_file(creds_path, 1, &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;
-}
+ if (creds_path == NULL) goto end;
+ creds_data = gpr_load_file(creds_path, 0, &file_ok);
+ if (!file_ok) goto end;
+ json = grpc_json_parse_string_with_len(
+ (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
+ if (json == NULL) goto end;
-/* Takes ownership of creds_path if not NULL. */
-static grpc_credentials *create_refresh_token_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, 1, &file_ok);
- gpr_free(creds_path);
- if (file_ok) {
- result = grpc_refresh_token_credentials_create(
- (const char *)GPR_SLICE_START_PTR(creds_data));
- gpr_slice_unref(creds_data);
+ /* First, try an auth json key. */
+ key = grpc_auth_json_key_create_from_json(json);
+ if (grpc_auth_json_key_is_valid(&key)) {
+ result = grpc_jwt_credentials_create_from_auth_json_key(
+ key, grpc_max_auth_token_lifetime);
+ goto end;
}
+
+ /* Then try a refresh token if the auth json key was invalid. */
+ token = grpc_auth_refresh_token_create_from_json(json);
+ if (grpc_auth_refresh_token_is_valid(&token)) {
+ result =
+ grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
+ goto end;
+ }
+
+end:
+ if (creds_path != NULL) gpr_free(creds_path);
+ gpr_slice_unref(creds_data);
+ if (json != NULL) grpc_json_destroy(json);
return result;
}
@@ -170,12 +173,12 @@
}
/* First, try the environment variable. */
- result =
- create_jwt_creds_from_path(gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
+ result = create_default_creds_from_path(
+ gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
if (result != NULL) goto end;
/* Then the well-known file. */
- result = create_refresh_token_creds_from_path(
+ result = create_default_creds_from_path(
grpc_get_well_known_google_credentials_file_path());
if (result != NULL) goto end;
@@ -193,11 +196,24 @@
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);
+ grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL);
+ default_credentials = grpc_credentials_ref(grpc_composite_credentials_create(
+ ssl_creds, result));
+ GPR_ASSERT(default_credentials != NULL);
+ grpc_credentials_unref(ssl_creds);
+ grpc_credentials_unref(result);
+ result = default_credentials;
}
gpr_mu_unlock(&g_mu);
return result;
}
+
+void grpc_flush_cached_google_default_credentials(void) {
+ gpr_once_init(&g_once, init_default_credentials);
+ gpr_mu_lock(&g_mu);
+ if (default_credentials != NULL) {
+ grpc_credentials_unref(default_credentials);
+ default_credentials = NULL;
+ }
+ gpr_mu_unlock(&g_mu);
+}
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
index 6116f1d..2e2b980 100644
--- a/src/core/security/json_token.c
+++ b/src/core/security/json_token.c
@@ -46,17 +46,11 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
-#include "src/core/json/json.h"
-
/* --- Constants. --- */
/* 1 hour max. */
const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0};
-#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
-#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
-#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
-
#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
#define GRPC_JWT_TYPE "JWT"
@@ -66,7 +60,7 @@
/* --- grpc_auth_json_key. --- */
-static const char *json_get_string_property(grpc_json *json,
+static const char *json_get_string_property(const grpc_json *json,
const char *prop_name) {
grpc_json *child;
for (child = json->child; child != NULL; child = child->next) {
@@ -79,7 +73,8 @@
return child->value;
}
-static int set_json_key_string_property(grpc_json *json, const char *prop_name,
+static int set_json_key_string_property(const grpc_json *json,
+ const char *prop_name,
char **json_key_field) {
const char *prop_value = json_get_string_property(json, prop_name);
if (prop_value == NULL) return 0;
@@ -92,11 +87,8 @@
strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID);
}
-grpc_auth_json_key grpc_auth_json_key_create_from_string(
- const char *json_string) {
+grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) {
grpc_auth_json_key result;
- char *scratchpad = gpr_strdup(json_string);
- grpc_json *json = grpc_json_parse_string(scratchpad);
BIO *bio = NULL;
const char *prop_value;
int success = 0;
@@ -104,7 +96,7 @@
memset(&result, 0, sizeof(grpc_auth_json_key));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
if (json == NULL) {
- gpr_log(GPR_ERROR, "Invalid json string %s", json_string);
+ gpr_log(GPR_ERROR, "Invalid json.");
goto end;
}
@@ -142,8 +134,16 @@
end:
if (bio != NULL) BIO_free(bio);
- if (json != NULL) grpc_json_destroy(json);
if (!success) grpc_auth_json_key_destruct(&result);
+ return result;
+}
+
+grpc_auth_json_key grpc_auth_json_key_create_from_string(
+ const char *json_string) {
+ char *scratchpad = gpr_strdup(json_string);
+ grpc_json *json = grpc_json_parse_string(scratchpad);
+ grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json);
+ if (json != NULL) grpc_json_destroy(json);
gpr_free(scratchpad);
return result;
}
@@ -342,18 +342,16 @@
strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID);
}
-grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
- const char *json_string) {
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
+ const grpc_json *json) {
grpc_auth_refresh_token result;
- char *scratchpad = gpr_strdup(json_string);
- grpc_json *json = grpc_json_parse_string(scratchpad);
const char *prop_value;
int success = 0;
memset(&result, 0, sizeof(grpc_auth_refresh_token));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
if (json == NULL) {
- gpr_log(GPR_ERROR, "Invalid json string %s", json_string);
+ gpr_log(GPR_ERROR, "Invalid json.");
goto end;
}
@@ -374,8 +372,17 @@
success = 1;
end:
- if (json != NULL) grpc_json_destroy(json);
if (!success) grpc_auth_refresh_token_destruct(&result);
+ return result;
+}
+
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
+ const char *json_string) {
+ char *scratchpad = gpr_strdup(json_string);
+ grpc_json *json = grpc_json_parse_string(scratchpad);
+ grpc_auth_refresh_token result =
+ grpc_auth_refresh_token_create_from_json(json);
+ if (json != NULL) grpc_json_destroy(json);
gpr_free(scratchpad);
return result;
}
diff --git a/src/core/security/json_token.h b/src/core/security/json_token.h
index 197796a..091dfef 100644
--- a/src/core/security/json_token.h
+++ b/src/core/security/json_token.h
@@ -37,10 +37,16 @@
#include <grpc/support/slice.h>
#include <openssl/rsa.h>
+#include "src/core/json/json.h"
+
/* --- Constants. --- */
#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
+#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
+#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
+#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
+
/* --- auth_json_key parsing. --- */
typedef struct {
@@ -59,6 +65,10 @@
grpc_auth_json_key grpc_auth_json_key_create_from_string(
const char *json_string);
+/* Creates a json_key object from parsed json. Returns an invalid object if a
+ parsing error has been encountered. */
+grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json);
+
/* Destructs the object. */
void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
@@ -97,6 +107,11 @@
grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
const char *json_string);
+/* Creates a refresh token object from parsed json. Returns an invalid object if
+ a parsing error has been encountered. */
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
+ const grpc_json *json);
+
/* Destructs the object. */
void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token);
diff --git a/src/node/health_check/health.js b/src/node/health_check/health.js
new file mode 100644
index 0000000..87e0019
--- /dev/null
+++ b/src/node/health_check/health.js
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+var grpc = require('../');
+
+var _ = require('lodash');
+
+var health_proto = grpc.load(__dirname + '/health.proto');
+
+var HealthClient = health_proto.grpc.health.v1alpha.Health;
+
+function HealthImplementation(statusMap) {
+ this.statusMap = _.clone(statusMap);
+}
+
+HealthImplementation.prototype.setStatus = function(host, service, status) {
+ if (!this.statusMap[host]) {
+ this.statusMap[host] = {};
+ }
+ this.statusMap[host][service] = status;
+};
+
+HealthImplementation.prototype.check = function(call, callback){
+ var host = call.request.host;
+ var service = call.request.service;
+ var status = _.get(this.statusMap, [host, service], null);
+ if (status === null) {
+ callback({code:grpc.status.NOT_FOUND});
+ } else {
+ callback(null, {status: status});
+ }
+};
+
+module.exports = {
+ Client: HealthClient,
+ service: HealthClient.service,
+ Implementation: HealthImplementation
+};
diff --git a/src/node/health_check/health.proto b/src/node/health_check/health.proto
new file mode 100644
index 0000000..d31df1e
--- /dev/null
+++ b/src/node/health_check/health.proto
@@ -0,0 +1,50 @@
+// 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.
+
+syntax = "proto3";
+
+package grpc.health.v1alpha;
+
+message HealthCheckRequest {
+ string host = 1;
+ string service = 2;
+}
+
+message HealthCheckResponse {
+ enum ServingStatus {
+ UNKNOWN = 0;
+ SERVING = 1;
+ NOT_SERVING = 2;
+ }
+ ServingStatus status = 1;
+}
+
+service Health {
+ rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
+}
\ No newline at end of file
diff --git a/src/node/src/server.js b/src/node/src/server.js
index c6cf9e7..9ac428f 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -634,7 +634,8 @@
}
var serialize = attrs.responseSerialize;
var deserialize = attrs.requestDeserialize;
- server.register(attrs.path, service_handlers[service_name][name],
+ server.register(attrs.path, _.bind(service_handlers[service_name][name],
+ service_handlers[service_name]),
serialize, deserialize, method_type);
});
}, this);
diff --git a/src/node/test/health_test.js b/src/node/test/health_test.js
new file mode 100644
index 0000000..4d1a508
--- /dev/null
+++ b/src/node/test/health_test.js
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+var assert = require('assert');
+
+var health = require('../health_check/health.js');
+
+var grpc = require('../');
+
+describe('Health Checking', function() {
+ var statusMap = {
+ '': {
+ '': 'SERVING',
+ 'grpc.test.TestService': 'NOT_SERVING',
+ },
+ virtual_host: {
+ 'grpc.test.TestService': 'SERVING'
+ }
+ };
+ var HealthServer = grpc.buildServer([health.service]);
+ var healthServer = new HealthServer({
+ 'grpc.health.v1alpha.Health': new health.Implementation(statusMap)
+ });
+ var healthClient;
+ before(function() {
+ var port_num = healthServer.bind('0.0.0.0:0');
+ healthServer.listen();
+ healthClient = new health.Client('localhost:' + port_num);
+ });
+ after(function() {
+ healthServer.shutdown();
+ });
+ it('should say an enabled service is SERVING', function(done) {
+ healthClient.check({service: ''}, function(err, response) {
+ assert.ifError(err);
+ assert.strictEqual(response.status, 'SERVING');
+ done();
+ });
+ });
+ it('should say that a disabled service is NOT_SERVING', function(done) {
+ healthClient.check({service: 'grpc.test.TestService'},
+ function(err, response) {
+ assert.ifError(err);
+ assert.strictEqual(response.status, 'NOT_SERVING');
+ done();
+ });
+ });
+ it('should say that a service on another host is SERVING', function(done) {
+ healthClient.check({host: 'virtual_host', service: 'grpc.test.TestService'},
+ function(err, response) {
+ assert.ifError(err);
+ assert.strictEqual(response.status, 'SERVING');
+ done();
+ });
+ });
+ it('should get NOT_FOUND if the service is not registered', function(done) {
+ healthClient.check({service: 'not_registered'}, function(err, response) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.NOT_FOUND);
+ done();
+ });
+ });
+ it('should get NOT_FOUND if the host is not registered', function(done) {
+ healthClient.check({host: 'wrong_host', service: 'grpc.test.TestService'},
+ function(err, response) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.NOT_FOUND);
+ done();
+ });
+ });
+});
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index e8bb730..d3fea96 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -37,12 +37,17 @@
#include "src/core/httpcli/httpcli.h"
#include "src/core/security/json_token.h"
+#include "src/core/support/env.h"
+#include "src/core/support/file.h"
#include "src/core/support/string.h"
+
+#include "test/core/util/test_config.h"
+
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
-#include "test/core/util/test_config.h"
+
#include <openssl/rsa.h>
static const char test_iam_authorization_token[] = "blahblahblhahb";
@@ -868,6 +873,68 @@
grpc_jwt_encode_and_sign_set_override(NULL);
}
+static void set_google_default_creds_env_var_with_file_contents(
+ const char *file_prefix, const char *contents) {
+ size_t contents_len = strlen(contents);
+ char *creds_file_name;
+ FILE *creds_file = gpr_tmpfile(file_prefix, &creds_file_name);
+ GPR_ASSERT(creds_file_name != NULL);
+ GPR_ASSERT(creds_file != NULL);
+ GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len);
+ fclose(creds_file);
+ gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name);
+ gpr_free(creds_file_name);
+}
+
+static grpc_credentials *composite_inner_creds(grpc_credentials *creds,
+ const char *inner_creds_type) {
+ size_t i;
+ grpc_composite_credentials *composite;
+ GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
+ composite = (grpc_composite_credentials *)creds;
+ for (i = 0; i < composite->inner.num_creds; i++) {
+ grpc_credentials *c = composite->inner.creds_array[i];
+ if (strcmp(c->type, inner_creds_type) == 0) return c;
+ }
+ GPR_ASSERT(0); /* Not found. */
+}
+
+static void test_google_default_creds_auth_key(void) {
+ grpc_jwt_credentials *jwt;
+ grpc_credentials *creds;
+ char *json_key = test_json_key_str();
+ grpc_flush_cached_google_default_credentials();
+ set_google_default_creds_env_var_with_file_contents(
+ "json_key_google_default_creds", json_key);
+ gpr_free(json_key);
+ creds = grpc_google_default_credentials_create();
+ GPR_ASSERT(creds != NULL);
+ jwt = (grpc_jwt_credentials *)composite_inner_creds(
+ creds, GRPC_CREDENTIALS_TYPE_JWT);
+ GPR_ASSERT(
+ strcmp(jwt->key.client_id,
+ "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
+ 0);
+ grpc_credentials_unref(creds);
+ gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
+}
+
+static void test_google_default_creds_access_token(void) {
+ grpc_refresh_token_credentials *refresh;
+ grpc_credentials *creds;
+ grpc_flush_cached_google_default_credentials();
+ set_google_default_creds_env_var_with_file_contents(
+ "refresh_token_google_default_creds", test_refresh_token_str);
+ creds = grpc_google_default_credentials_create();
+ GPR_ASSERT(creds != NULL);
+ refresh = (grpc_refresh_token_credentials *)composite_inner_creds(
+ creds, GRPC_CREDENTIALS_TYPE_OAUTH2);
+ GPR_ASSERT(strcmp(refresh->refresh_token.client_id,
+ "32555999999.apps.googleusercontent.com") == 0);
+ grpc_credentials_unref(creds);
+ gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
+}
+
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_empty_md_store();
@@ -896,5 +963,7 @@
test_service_account_creds_signing_failure();
test_jwt_creds_success();
test_jwt_creds_signing_failure();
+ test_google_default_creds_auth_key();
+ test_google_default_creds_access_token();
return 0;
}
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
index 6f8fb8f..a1819dc 100644
--- a/test/cpp/common/secure_auth_context_test.cc
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -59,12 +59,12 @@
SecureAuthContext context(ctx);
std::vector<grpc::string> peer_identity = context.GetPeerIdentity();
- EXPECT_EQ(2, peer_identity.size());
+ EXPECT_EQ(2u, peer_identity.size());
EXPECT_EQ("chapi", peer_identity[0]);
EXPECT_EQ("chapo", peer_identity[1]);
EXPECT_EQ("name", context.GetPeerIdentityPropertyName());
std::vector<grpc::string> bar = context.FindPropertyValues("foo");
- EXPECT_EQ(1, bar.size());
+ EXPECT_EQ(1u, bar.size());
EXPECT_EQ("bar", bar[0]);
}
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 0912b19..3791d15 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -88,7 +88,7 @@
std::shared_ptr<const AuthContext> auth_ctx = context->auth_context();
std::vector<grpc::string> fake =
auth_ctx->FindPropertyValues("transport_security_type");
- EXPECT_EQ(1, fake.size());
+ EXPECT_EQ(1u, fake.size());
EXPECT_EQ("fake", fake[0]);
EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty());
EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty());