summaryrefslogtreecommitdiff
path: root/grpc/src/core/lib/security/credentials
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2020-11-19 19:03:52 +0100
committerJeff Vander Stoep <jeffv@google.com>2020-11-23 12:00:30 +0100
commit08902cf05eddf53e0ba8ccd8a4b12d615d3445e3 (patch)
tree780528631811bd11e8ff44b3c485e8ee2b1972f9 /grpc/src/core/lib/security/credentials
parent98a8525e013e1356d5914fbf7a20a142bdc96f7b (diff)
downloadgrpcio-sys-08902cf05eddf53e0ba8ccd8a4b12d615d3445e3.tar.gz
Upgrade to 0.7.1
Test: build, TH Change-Id: I3cb2c39b931e2b5c5b1a0bf775c6185c0e521da8
Diffstat (limited to 'grpc/src/core/lib/security/credentials')
-rw-r--r--grpc/src/core/lib/security/credentials/composite/composite_credentials.h6
-rw-r--r--grpc/src/core/lib/security/credentials/credentials.h13
-rw-r--r--grpc/src/core/lib/security/credentials/google_default/credentials_generic.cc14
-rw-r--r--grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc118
-rw-r--r--grpc/src/core/lib/security/credentials/jwt/json_token.h5
-rw-r--r--grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc11
-rw-r--r--grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc21
-rw-r--r--grpc/src/core/lib/security/credentials/jwt/jwt_verifier.h5
-rw-r--r--grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc97
-rw-r--r--grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h5
-rw-r--r--grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc12
-rw-r--r--grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc20
-rw-r--r--grpc/src/core/lib/security/credentials/ssl/ssl_credentials.h10
-rw-r--r--grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc321
-rw-r--r--grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h214
-rw-r--r--grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h16
-rw-r--r--grpc/src/core/lib/security/credentials/xds/xds_credentials.cc45
-rw-r--r--grpc/src/core/lib/security/credentials/xds/xds_credentials.h51
18 files changed, 829 insertions, 155 deletions
diff --git a/grpc/src/core/lib/security/credentials/composite/composite_credentials.h b/grpc/src/core/lib/security/credentials/composite/composite_credentials.h
index 57967e1b..6b9e9d11 100644
--- a/grpc/src/core/lib/security/credentials/composite/composite_credentials.h
+++ b/grpc/src/core/lib/security/credentials/composite/composite_credentials.h
@@ -23,7 +23,8 @@
#include <string>
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "absl/container/inlined_vector.h"
+
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/security/credentials/credentials.h"
@@ -71,8 +72,7 @@ class grpc_composite_channel_credentials : public grpc_channel_credentials {
class grpc_composite_call_credentials : public grpc_call_credentials {
public:
using CallCredentialsList =
- grpc_core::InlinedVector<grpc_core::RefCountedPtr<grpc_call_credentials>,
- 2>;
+ absl::InlinedVector<grpc_core::RefCountedPtr<grpc_call_credentials>, 2>;
grpc_composite_call_credentials(
grpc_core::RefCountedPtr<grpc_call_credentials> creds1,
diff --git a/grpc/src/core/lib/security/credentials/credentials.h b/grpc/src/core/lib/security/credentials/credentials.h
index e7385537..1cc6e2d6 100644
--- a/grpc/src/core/lib/security/credentials/credentials.h
+++ b/grpc/src/core/lib/security/credentials/credentials.h
@@ -23,6 +23,8 @@
#include <string.h>
+#include <string>
+
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/sync.h>
@@ -79,13 +81,13 @@ typedef enum {
/* --- Google utils --- */
/* It is the caller's responsibility to gpr_free the result if not NULL. */
-char* grpc_get_well_known_google_credentials_file_path(void);
+std::string 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);
+std::string 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);
+typedef std::string (*grpc_well_known_credentials_path_getter)(void);
void grpc_override_well_known_credentials_path_getter(
grpc_well_known_credentials_path_getter getter);
@@ -148,11 +150,10 @@ grpc_channel_credentials* grpc_channel_credentials_find_in_args(
/* --- grpc_credentials_mdelem_array. --- */
-typedef struct {
+struct grpc_credentials_mdelem_array {
grpc_mdelem* md = nullptr;
size_t size = 0;
-} grpc_credentials_mdelem_array;
-
+};
/// Takes a new ref to \a md.
void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array* list,
grpc_mdelem md);
diff --git a/grpc/src/core/lib/security/credentials/google_default/credentials_generic.cc b/grpc/src/core/lib/security/credentials/google_default/credentials_generic.cc
index 10ff0f62..8716edec 100644
--- a/grpc/src/core/lib/security/credentials/google_default/credentials_generic.cc
+++ b/grpc/src/core/lib/security/credentials/google_default/credentials_generic.cc
@@ -20,22 +20,24 @@
#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
+#include <string>
+
+#include "absl/strings/str_cat.h"
+
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/string.h"
-char* grpc_get_well_known_google_credentials_file_path_impl(void) {
- char* result = nullptr;
+std::string grpc_get_well_known_google_credentials_file_path_impl(void) {
char* base = gpr_getenv(GRPC_GOOGLE_CREDENTIALS_PATH_ENV_VAR);
if (base == nullptr) {
gpr_log(GPR_ERROR, "Could not get " GRPC_GOOGLE_CREDENTIALS_PATH_ENV_VAR
" environment variable.");
- return nullptr;
+ return "";
}
- gpr_asprintf(&result, "%s/%s", base, GRPC_GOOGLE_CREDENTIALS_PATH_SUFFIX);
+ std::string result =
+ absl::StrCat(base, "/", GRPC_GOOGLE_CREDENTIALS_PATH_SUFFIX);
gpr_free(base);
return result;
}
diff --git a/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index 58e550ed..9162bad4 100644
--- a/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -49,6 +49,8 @@ using grpc_core::Json;
/* -- Constants. -- */
#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal."
+#define GRPC_GOOGLE_CREDENTIAL_CREATION_ERROR \
+ "Failed to create Google credentials"
/* -- Default credentials. -- */
@@ -57,7 +59,6 @@ using grpc_core::Json;
* means the detection is done via network test that is unreliable and the
* unreliable result should not be referred by successive calls. */
static int g_metadata_server_available = 0;
-static int g_is_on_gce = 0;
static gpr_mu g_state_mu;
/* Protect a metadata_server_detector instance that can be modified by more than
* one gRPC threads */
@@ -68,13 +69,12 @@ static grpc_core::internal::grpc_gce_tenancy_checker g_gce_tenancy_checker =
static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); }
-typedef struct {
+struct metadata_server_detector {
grpc_polling_entity pollent;
int is_done;
int success;
grpc_http_response response;
-} metadata_server_detector;
-
+};
grpc_core::RefCountedPtr<grpc_channel_security_connector>
grpc_google_default_channel_credentials::create_security_connector(
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
@@ -90,7 +90,7 @@ grpc_google_default_channel_credentials::create_security_connector(
bool use_alts =
is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer;
/* Return failure if ALTS is selected but not running on GCE. */
- if (use_alts && !g_is_on_gce) {
+ if (use_alts && alts_creds_ == nullptr) {
gpr_log(GPR_ERROR, "ALTS is selected, but not running on GCE.");
return nullptr;
}
@@ -217,24 +217,21 @@ static int is_metadata_server_reachable() {
/* Takes ownership of creds_path if not NULL. */
static grpc_error* create_default_creds_from_path(
- char* creds_path, grpc_core::RefCountedPtr<grpc_call_credentials>* creds) {
+ const std::string& creds_path,
+ grpc_core::RefCountedPtr<grpc_call_credentials>* creds) {
grpc_auth_json_key key;
grpc_auth_refresh_token token;
grpc_core::RefCountedPtr<grpc_call_credentials> result;
grpc_slice creds_data = grpc_empty_slice();
grpc_error* error = GRPC_ERROR_NONE;
Json json;
- grpc_core::StringView str;
- if (creds_path == nullptr) {
+ if (creds_path.empty()) {
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("creds_path unset");
goto end;
}
- error = grpc_load_file(creds_path, 0, &creds_data);
+ error = grpc_load_file(creds_path.c_str(), 0, &creds_data);
if (error != GRPC_ERROR_NONE) goto end;
- str = grpc_core::StringView(
- reinterpret_cast<char*>(GRPC_SLICE_START_PTR(creds_data)),
- GRPC_SLICE_LENGTH(creds_data));
- json = Json::Parse(str, &error);
+ json = Json::Parse(grpc_core::StringViewFromSlice(creds_data), &error);
if (error != GRPC_ERROR_NONE) goto end;
if (json.type() != Json::Type::OBJECT) {
error = grpc_error_set_str(
@@ -272,42 +269,18 @@ static grpc_error* create_default_creds_from_path(
end:
GPR_ASSERT((result == nullptr) + (error == GRPC_ERROR_NONE) == 1);
- if (creds_path != nullptr) gpr_free(creds_path);
grpc_slice_unref_internal(creds_data);
*creds = result;
return error;
}
-grpc_channel_credentials* grpc_google_default_credentials_create() {
- grpc_channel_credentials* result = nullptr;
- grpc_core::RefCountedPtr<grpc_call_credentials> call_creds;
- grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "Failed to create Google credentials");
- grpc_error* err;
- grpc_core::ExecCtx exec_ctx;
-
- GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
-
+static void update_tenancy() {
gpr_once_init(&g_once, init_default_credentials);
-
- /* First, try the environment variable. */
- err = create_default_creds_from_path(
- gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
- if (err == GRPC_ERROR_NONE) goto end;
- error = grpc_error_add_child(error, err);
-
- /* Then the well-known file. */
- err = create_default_creds_from_path(
- grpc_get_well_known_google_credentials_file_path(), &call_creds);
- if (err == GRPC_ERROR_NONE) goto end;
- error = grpc_error_add_child(error, err);
-
- gpr_mu_lock(&g_state_mu);
+ grpc_core::MutexLock lock(&g_state_mu);
/* Try a platform-provided hint for GCE. */
if (!g_metadata_server_available) {
- g_is_on_gce = g_gce_tenancy_checker();
- g_metadata_server_available = g_is_on_gce;
+ g_metadata_server_available = g_gce_tenancy_checker();
}
/* TODO: Add a platform-provided hint for GAE. */
@@ -315,19 +288,64 @@ grpc_channel_credentials* grpc_google_default_credentials_create() {
if (!g_metadata_server_available) {
g_metadata_server_available = is_metadata_server_reachable();
}
- gpr_mu_unlock(&g_state_mu);
+}
+
+static bool metadata_server_available() {
+ grpc_core::MutexLock lock(&g_state_mu);
+ return static_cast<bool>(g_metadata_server_available);
+}
- if (g_metadata_server_available) {
+static grpc_core::RefCountedPtr<grpc_call_credentials> make_default_call_creds(
+ grpc_error** error) {
+ grpc_core::RefCountedPtr<grpc_call_credentials> call_creds;
+ grpc_error* err;
+
+ /* First, try the environment variable. */
+ char* path_from_env = gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR);
+ if (path_from_env != nullptr) {
+ err = create_default_creds_from_path(path_from_env, &call_creds);
+ gpr_free(path_from_env);
+ if (err == GRPC_ERROR_NONE) return call_creds;
+ *error = grpc_error_add_child(*error, err);
+ }
+
+ /* Then the well-known file. */
+ err = create_default_creds_from_path(
+ grpc_get_well_known_google_credentials_file_path(), &call_creds);
+ if (err == GRPC_ERROR_NONE) return call_creds;
+ *error = grpc_error_add_child(*error, err);
+
+ update_tenancy();
+
+ if (metadata_server_available()) {
call_creds = grpc_core::RefCountedPtr<grpc_call_credentials>(
grpc_google_compute_engine_credentials_create(nullptr));
if (call_creds == nullptr) {
- error = grpc_error_add_child(
- error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "Failed to get credentials from network"));
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ GRPC_GOOGLE_CREDENTIAL_CREATION_ERROR);
+ *error = grpc_error_add_child(
+ *error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Failed to get credentials from network"));
}
}
-end:
+ return call_creds;
+}
+
+grpc_channel_credentials* grpc_google_default_credentials_create(
+ grpc_call_credentials* call_credentials) {
+ grpc_channel_credentials* result = nullptr;
+ grpc_core::RefCountedPtr<grpc_call_credentials> call_creds(call_credentials);
+ grpc_error* error = nullptr;
+ grpc_core::ExecCtx exec_ctx;
+
+ GRPC_API_TRACE("grpc_google_default_credentials_create(%p)", 1,
+ (call_credentials));
+
+ if (call_creds == nullptr) {
+ call_creds = make_default_call_creds(&error);
+ }
+
if (call_creds != nullptr) {
/* Create google default credentials. */
grpc_channel_credentials* ssl_creds =
@@ -340,10 +358,8 @@ end:
grpc_alts_credentials_options_destroy(options);
auto creds =
grpc_core::MakeRefCounted<grpc_google_default_channel_credentials>(
- alts_creds != nullptr ? alts_creds->Ref() : nullptr,
- ssl_creds != nullptr ? ssl_creds->Ref() : nullptr);
- if (ssl_creds) ssl_creds->Unref();
- if (alts_creds) alts_creds->Unref();
+ grpc_core::RefCountedPtr<grpc_channel_credentials>(alts_creds),
+ grpc_core::RefCountedPtr<grpc_channel_credentials>(ssl_creds));
result = grpc_composite_channel_credentials_create(
creds.get(), call_creds.get(), nullptr);
GPR_ASSERT(result != nullptr);
@@ -377,7 +393,7 @@ void grpc_flush_cached_google_default_credentials(void) {
static grpc_well_known_credentials_path_getter creds_path_getter = nullptr;
-char* grpc_get_well_known_google_credentials_file_path(void) {
+std::string grpc_get_well_known_google_credentials_file_path(void) {
if (creds_path_getter != nullptr) return creds_path_getter();
return grpc_get_well_known_google_credentials_file_path_impl();
}
diff --git a/grpc/src/core/lib/security/credentials/jwt/json_token.h b/grpc/src/core/lib/security/credentials/jwt/json_token.h
index 23887b09..b9a41c6b 100644
--- a/grpc/src/core/lib/security/credentials/jwt/json_token.h
+++ b/grpc/src/core/lib/security/credentials/jwt/json_token.h
@@ -32,14 +32,13 @@
/* --- auth_json_key parsing. --- */
-typedef struct {
+struct grpc_auth_json_key {
const char* type;
char* private_key_id;
char* client_id;
char* client_email;
RSA* private_key;
-} grpc_auth_json_key;
-
+};
/* Returns 1 if the object is valid, 0 otherwise. */
int grpc_auth_json_key_is_valid(const grpc_auth_json_key* json_key);
diff --git a/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc b/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc
index bed594e5..e5edc052 100644
--- a/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc
+++ b/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc
@@ -23,8 +23,13 @@
#include <inttypes.h>
#include <string.h>
+#include <string>
+
+#include "absl/strings/str_cat.h"
+
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h"
#include <grpc/support/alloc.h>
@@ -81,16 +86,14 @@ bool grpc_service_account_jwt_access_credentials::get_request_metadata(
jwt = grpc_jwt_encode_and_sign(&key_, context.service_url, jwt_lifetime_,
nullptr);
if (jwt != nullptr) {
- char* md_value;
- gpr_asprintf(&md_value, "Bearer %s", jwt);
+ std::string md_value = absl::StrCat("Bearer ", jwt);
gpr_free(jwt);
cached_.jwt_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), jwt_lifetime_);
cached_.service_url = gpr_strdup(context.service_url);
cached_.jwt_md = grpc_mdelem_from_slices(
grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
- grpc_slice_from_copied_string(md_value));
- gpr_free(md_value);
+ grpc_slice_from_cpp_string(std::move(md_value)));
jwt_md = GRPC_MDELEM_REF(cached_.jwt_md);
}
gpr_mu_unlock(&cache_mu_);
diff --git a/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc
index 1d082b25..cd8217fd 100644
--- a/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc
+++ b/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc
@@ -86,9 +86,7 @@ static Json parse_json_part_from_jwt(const char* str, size_t len) {
gpr_log(GPR_ERROR, "Invalid base64.");
return Json(); // JSON null
}
- grpc_core::StringView string(
- reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
- GRPC_SLICE_LENGTH(slice));
+ absl::string_view string = grpc_core::StringViewFromSlice(slice);
grpc_error* error = GRPC_ERROR_NONE;
Json json = Json::Parse(string, &error);
if (error != GRPC_ERROR_NONE) {
@@ -120,14 +118,13 @@ static gpr_timespec validate_time_field(const Json& json, const char* key) {
/* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */
-typedef struct {
+struct jose_header {
const char* alg;
const char* kid;
const char* typ;
/* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */
grpc_core::ManualConstructor<Json> json;
-} jose_header;
-
+};
static void jose_header_destroy(jose_header* h) {
h->json.Destroy();
gpr_free(h);
@@ -337,7 +334,7 @@ typedef enum {
HTTP_RESPONSE_COUNT /* must be last */
} http_response_index;
-typedef struct {
+struct verifier_cb_ctx {
grpc_jwt_verifier* verifier;
grpc_polling_entity pollent;
jose_header* header;
@@ -348,8 +345,7 @@ typedef struct {
void* user_data;
grpc_jwt_verification_done_cb user_cb;
grpc_http_response responses[HTTP_RESPONSE_COUNT];
-} verifier_cb_ctx;
-
+};
/* Takes ownership of the header, claims and signature. */
static verifier_cb_ctx* verifier_cb_ctx_create(
grpc_jwt_verifier* verifier, grpc_pollset* pollset, jose_header* header,
@@ -394,11 +390,10 @@ gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN};
/* Max delay defaults to one minute. */
grpc_millis grpc_jwt_verifier_max_delay = 60 * GPR_MS_PER_SEC;
-typedef struct {
+struct email_key_mapping {
char* email_domain;
char* key_url_prefix;
-} email_key_mapping;
-
+};
struct grpc_jwt_verifier {
email_key_mapping* mappings;
size_t num_mappings; /* Should be very few, linear search ok. */
@@ -418,7 +413,7 @@ static Json json_from_http(const grpc_httpcli_response* response) {
}
grpc_error* error = GRPC_ERROR_NONE;
Json json = Json::Parse(
- grpc_core::StringView(response->body, response->body_length), &error);
+ absl::string_view(response->body, response->body_length), &error);
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR, "Invalid JSON found in response.");
return Json(); // JSON null
diff --git a/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.h b/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.h
index d4483866..66ddbf22 100644
--- a/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.h
+++ b/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.h
@@ -71,7 +71,7 @@ gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims* claims);
typedef struct grpc_jwt_verifier grpc_jwt_verifier;
-typedef struct {
+struct grpc_jwt_verifier_email_domain_key_url_mapping {
/* The email domain is the part after the @ sign. */
const char* email_domain;
@@ -79,8 +79,7 @@ typedef struct {
https://<key_url_prefix>/<issuer_email>
Therefore the key_url_prefix must NOT contain https://. */
const char* key_url_prefix;
-} grpc_jwt_verifier_email_domain_key_url_mapping;
-
+};
/* Globals to control the verifier. Not thread-safe. */
extern gpr_timespec grpc_jwt_verifier_clock_skew;
extern grpc_millis grpc_jwt_verifier_max_delay;
diff --git a/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
index c922d35b..322156c9 100644
--- a/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
+++ b/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
@@ -23,6 +23,11 @@
#include <string.h>
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
#include <grpc/grpc_security.h>
#include <grpc/impl/codegen/slice.h>
#include <grpc/slice.h>
@@ -30,9 +35,7 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
-#include "absl/strings/str_format.h"
#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/load_file.h"
@@ -134,7 +137,6 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
const grpc_http_response* response, grpc_mdelem* token_md,
grpc_millis* token_lifetime) {
char* null_terminated_body = nullptr;
- char* new_access_token = nullptr;
grpc_credentials_status status = GRPC_CREDENTIALS_OK;
Json json;
@@ -200,12 +202,12 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
goto end;
}
expires_in = it->second.string_value().c_str();
- gpr_asprintf(&new_access_token, "%s %s", token_type, access_token);
*token_lifetime = strtol(expires_in, nullptr, 10) * GPR_MS_PER_SEC;
if (!GRPC_MDISNULL(*token_md)) GRPC_MDELEM_UNREF(*token_md);
*token_md = grpc_mdelem_from_slices(
grpc_core::ExternallyManagedSlice(GRPC_AUTHORIZATION_METADATA_KEY),
- grpc_core::UnmanagedMemorySlice(new_access_token));
+ grpc_slice_from_cpp_string(
+ absl::StrCat(token_type, " ", access_token)));
status = GRPC_CREDENTIALS_OK;
}
@@ -214,8 +216,7 @@ end:
GRPC_MDELEM_UNREF(*token_md);
*token_md = GRPC_MDNULL;
}
- if (null_terminated_body != nullptr) gpr_free(null_terminated_body);
- if (new_access_token != nullptr) gpr_free(new_access_token);
+ gpr_free(null_terminated_body);
return status;
}
@@ -440,10 +441,9 @@ void grpc_google_refresh_token_credentials::fetch_oauth2(
const_cast<char*>("Content-Type"),
const_cast<char*>("application/x-www-form-urlencoded")};
grpc_httpcli_request request;
- char* body = nullptr;
- gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
- refresh_token_.client_id, refresh_token_.client_secret,
- refresh_token_.refresh_token);
+ std::string body = absl::StrFormat(
+ GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, refresh_token_.client_id,
+ refresh_token_.client_secret, refresh_token_.refresh_token);
memset(&request, 0, sizeof(grpc_httpcli_request));
request.host = (char*)GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
request.http.path = (char*)GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
@@ -455,13 +455,12 @@ void grpc_google_refresh_token_credentials::fetch_oauth2(
extreme memory pressure. */
grpc_resource_quota* resource_quota =
grpc_resource_quota_create("oauth2_credentials_refresh");
- grpc_httpcli_post(httpcli_context, pollent, resource_quota, &request, body,
- strlen(body), deadline,
+ grpc_httpcli_post(httpcli_context, pollent, resource_quota, &request,
+ body.c_str(), body.size(), deadline,
GRPC_CLOSURE_INIT(&http_post_cb_closure_, response_cb,
metadata_req, grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_resource_quota_unref_internal(resource_quota);
- gpr_free(body);
}
grpc_google_refresh_token_credentials::grpc_google_refresh_token_credentials(
@@ -485,16 +484,15 @@ std::string grpc_google_refresh_token_credentials::debug_string() {
grpc_oauth2_token_fetcher_credentials::debug_string());
}
-static char* create_loggable_refresh_token(grpc_auth_refresh_token* token) {
+static std::string create_loggable_refresh_token(
+ grpc_auth_refresh_token* token) {
if (strcmp(token->type, GRPC_AUTH_JSON_TYPE_INVALID) == 0) {
- return gpr_strdup("<Invalid json token>");
+ return "<Invalid json token>";
}
- char* loggable_token = nullptr;
- gpr_asprintf(&loggable_token,
- "{\n type: %s\n client_id: %s\n client_secret: "
- "<redacted>\n refresh_token: <redacted>\n}",
- token->type, token->client_id);
- return loggable_token;
+ return absl::StrFormat(
+ "{\n type: %s\n client_id: %s\n client_secret: "
+ "<redacted>\n refresh_token: <redacted>\n}",
+ token->type, token->client_id);
}
grpc_call_credentials* grpc_google_refresh_token_credentials_create(
@@ -502,12 +500,10 @@ grpc_call_credentials* grpc_google_refresh_token_credentials_create(
grpc_auth_refresh_token token =
grpc_auth_refresh_token_create_from_string(json_refresh_token);
if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace)) {
- char* loggable_token = create_loggable_refresh_token(&token);
gpr_log(GPR_INFO,
"grpc_refresh_token_credentials_create(json_refresh_token=%s, "
"reserved=%p)",
- loggable_token, reserved);
- gpr_free(loggable_token);
+ create_loggable_refresh_token(&token).c_str(), reserved);
}
GPR_ASSERT(reserved == nullptr);
return grpc_refresh_token_credentials_create_from_auth_refresh_token(token)
@@ -522,12 +518,10 @@ namespace grpc_core {
namespace {
-void MaybeAddToBody(gpr_strvec* body_strvec, const char* field_name,
- const char* field) {
+void MaybeAddToBody(const char* field_name, const char* field,
+ std::vector<std::string>* body) {
if (field == nullptr || strlen(field) == 0) return;
- char* new_query;
- gpr_asprintf(&new_query, "&%s=%s", field_name, field);
- gpr_strvec_add(body_strvec, new_query);
+ body->push_back(absl::StrFormat("&%s=%s", field_name, field));
}
grpc_error* LoadTokenFile(const char* path, gpr_slice* token) {
@@ -607,20 +601,18 @@ class StsTokenFetcherCredentials
grpc_error* FillBody(char** body, size_t* body_length) {
*body = nullptr;
- gpr_strvec body_strvec;
- gpr_strvec_init(&body_strvec);
+ std::vector<std::string> body_parts;
grpc_slice subject_token = grpc_empty_slice();
grpc_slice actor_token = grpc_empty_slice();
grpc_error* err = GRPC_ERROR_NONE;
- auto cleanup = [&body, &body_length, &body_strvec, &subject_token,
+ auto cleanup = [&body, &body_length, &body_parts, &subject_token,
&actor_token, &err]() {
if (err == GRPC_ERROR_NONE) {
- *body = gpr_strvec_flatten(&body_strvec, body_length);
- } else {
- gpr_free(*body);
+ std::string body_str = absl::StrJoin(body_parts, "");
+ *body = gpr_strdup(body_str.c_str());
+ *body_length = body_str.size();
}
- gpr_strvec_destroy(&body_strvec);
grpc_slice_unref_internal(subject_token);
grpc_slice_unref_internal(actor_token);
return err;
@@ -628,23 +620,23 @@ class StsTokenFetcherCredentials
err = LoadTokenFile(subject_token_path_.get(), &subject_token);
if (err != GRPC_ERROR_NONE) return cleanup();
- gpr_asprintf(
- body, GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
+ body_parts.push_back(absl::StrFormat(
+ GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)),
- subject_token_type_.get());
- gpr_strvec_add(&body_strvec, *body);
- MaybeAddToBody(&body_strvec, "resource", resource_.get());
- MaybeAddToBody(&body_strvec, "audience", audience_.get());
- MaybeAddToBody(&body_strvec, "scope", scope_.get());
- MaybeAddToBody(&body_strvec, "requested_token_type",
- requested_token_type_.get());
+ subject_token_type_.get()));
+ MaybeAddToBody("resource", resource_.get(), &body_parts);
+ MaybeAddToBody("audience", audience_.get(), &body_parts);
+ MaybeAddToBody("scope", scope_.get(), &body_parts);
+ MaybeAddToBody("requested_token_type", requested_token_type_.get(),
+ &body_parts);
if ((actor_token_path_ != nullptr) && *actor_token_path_ != '\0') {
err = LoadTokenFile(actor_token_path_.get(), &actor_token);
if (err != GRPC_ERROR_NONE) return cleanup();
MaybeAddToBody(
- &body_strvec, "actor_token",
- reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token)));
- MaybeAddToBody(&body_strvec, "actor_token_type", actor_token_type_.get());
+ "actor_token",
+ reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token)),
+ &body_parts);
+ MaybeAddToBody("actor_token_type", actor_token_type_.get(), &body_parts);
}
return cleanup();
}
@@ -669,7 +661,7 @@ grpc_error* ValidateStsCredentialsOptions(
void operator()(grpc_uri* uri) { grpc_uri_destroy(uri); }
};
*sts_url_out = nullptr;
- InlinedVector<grpc_error*, 3> error_list;
+ absl::InlinedVector<grpc_error*, 3> error_list;
std::unique_ptr<grpc_uri, GrpcUriDeleter> sts_url(
options->token_exchange_service_uri != nullptr
? grpc_uri_parse(options->token_exchange_service_uri, false)
@@ -746,13 +738,10 @@ void grpc_access_token_credentials::cancel_get_request_metadata(
grpc_access_token_credentials::grpc_access_token_credentials(
const char* access_token)
: grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) {
- char* token_md_value;
- gpr_asprintf(&token_md_value, "Bearer %s", access_token);
grpc_core::ExecCtx exec_ctx;
access_token_md_ = grpc_mdelem_from_slices(
grpc_core::ExternallyManagedSlice(GRPC_AUTHORIZATION_METADATA_KEY),
- grpc_core::UnmanagedMemorySlice(token_md_value));
- gpr_free(token_md_value);
+ grpc_slice_from_cpp_string(absl::StrCat("Bearer ", access_token)));
}
std::string grpc_access_token_credentials::debug_string() {
diff --git a/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 9065da4f..2a9b37e1 100644
--- a/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -34,13 +34,12 @@
"s&subject_token_type=%s"
// auth_refresh_token parsing.
-typedef struct {
+struct grpc_auth_refresh_token {
const char* type;
char* client_id;
char* client_secret;
char* refresh_token;
-} grpc_auth_refresh_token;
-
+};
/// Returns 1 if the object is valid, 0 otherwise.
int grpc_auth_refresh_token_is_valid(
const grpc_auth_refresh_token* refresh_token);
diff --git a/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc b/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc
index ebe59212..9cb8b815 100644
--- a/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc
+++ b/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc
@@ -22,10 +22,11 @@
#include <string.h>
+#include "absl/strings/str_cat.h"
+
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include "src/core/lib/slice/slice_internal.h"
@@ -86,11 +87,10 @@ static grpc_error* process_plugin_result(
size_t num_md, grpc_status_code status, const char* error_details) {
grpc_error* error = GRPC_ERROR_NONE;
if (status != GRPC_STATUS_OK) {
- char* msg;
- gpr_asprintf(&msg, "Getting metadata from plugin failed with error: %s",
- error_details);
- error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
- gpr_free(msg);
+ error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("Getting metadata from plugin failed with error: ",
+ error_details)
+ .c_str());
} else {
bool seen_illegal_header = false;
for (size_t i = 0; i < num_md; ++i) {
diff --git a/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc
index 48d78f39..3bb7790f 100644
--- a/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc
+++ b/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc
@@ -117,6 +117,16 @@ void grpc_ssl_credentials::build_config(
}
}
+void grpc_ssl_credentials::set_min_tls_version(
+ grpc_tls_version min_tls_version) {
+ config_.min_tls_version = min_tls_version;
+}
+
+void grpc_ssl_credentials::set_max_tls_version(
+ grpc_tls_version max_tls_version) {
+ config_.max_tls_version = max_tls_version;
+}
+
/* Deprecated in favor of grpc_ssl_credentials_create_ex. Will be removed
* once all of its call sites are migrated to grpc_ssl_credentials_create_ex. */
grpc_channel_credentials* grpc_ssl_credentials_create(
@@ -213,6 +223,16 @@ void grpc_ssl_server_credentials::build_config(
config_.num_key_cert_pairs = num_key_cert_pairs;
}
+void grpc_ssl_server_credentials::set_min_tls_version(
+ grpc_tls_version min_tls_version) {
+ config_.min_tls_version = min_tls_version;
+}
+
+void grpc_ssl_server_credentials::set_max_tls_version(
+ grpc_tls_version max_tls_version) {
+ config_.max_tls_version = max_tls_version;
+}
+
grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create(
const char* pem_root_certs,
const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
diff --git a/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.h b/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.h
index 545a27f0..4c90813f 100644
--- a/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.h
+++ b/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.h
@@ -38,6 +38,11 @@ class grpc_ssl_credentials : public grpc_channel_credentials {
const char* target, const grpc_channel_args* args,
grpc_channel_args** new_args) override;
+ // TODO(mattstev): Plumb to wrapped languages. Until then, setting the TLS
+ // version should be done for testing purposes only.
+ void set_min_tls_version(grpc_tls_version min_tls_version);
+ void set_max_tls_version(grpc_tls_version max_tls_version);
+
private:
void build_config(const char* pem_root_certs,
grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
@@ -77,6 +82,11 @@ class grpc_ssl_server_credentials final : public grpc_server_credentials {
config);
}
+ // TODO(mattstev): Plumb to wrapped languages. Until then, setting the TLS
+ // version should be done for testing purposes only.
+ void set_min_tls_version(grpc_tls_version min_tls_version);
+ void set_max_tls_version(grpc_tls_version max_tls_version);
+
const grpc_ssl_server_config& config() const { return config_; }
private:
diff --git a/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
new file mode 100644
index 00000000..2189865b
--- /dev/null
+++ b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
@@ -0,0 +1,321 @@
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <stdlib.h>
+#include <string.h>
+
+void grpc_tls_certificate_distributor::SetKeyMaterials(
+ const std::string& cert_name, absl::optional<std::string> pem_root_certs,
+ absl::optional<PemKeyCertPairList> pem_key_cert_pairs) {
+ GPR_ASSERT(pem_root_certs.has_value() || pem_key_cert_pairs.has_value());
+ grpc_core::MutexLock lock(&mu_);
+ auto& cert_info = certificate_info_map_[cert_name];
+ if (pem_root_certs.has_value()) {
+ // Successful credential updates will clear any pre-existing error.
+ cert_info.SetRootError(GRPC_ERROR_NONE);
+ for (auto* watcher_ptr : cert_info.root_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ GPR_ASSERT(watcher_it->second.root_cert_name.has_value());
+ absl::optional<PemKeyCertPairList> pem_key_cert_pairs_to_report;
+ if (pem_key_cert_pairs.has_value() &&
+ watcher_it->second.identity_cert_name == cert_name) {
+ pem_key_cert_pairs_to_report = pem_key_cert_pairs;
+ } else if (watcher_it->second.identity_cert_name.has_value()) {
+ auto& identity_cert_info =
+ certificate_info_map_[*watcher_it->second.identity_cert_name];
+ pem_key_cert_pairs_to_report = identity_cert_info.pem_key_cert_pairs;
+ }
+ watcher_ptr->OnCertificatesChanged(
+ pem_root_certs, std::move(pem_key_cert_pairs_to_report));
+ }
+ cert_info.pem_root_certs = std::move(*pem_root_certs);
+ }
+ if (pem_key_cert_pairs.has_value()) {
+ // Successful credential updates will clear any pre-existing error.
+ cert_info.SetIdentityError(GRPC_ERROR_NONE);
+ for (const auto watcher_ptr : cert_info.identity_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ GPR_ASSERT(watcher_it->second.identity_cert_name.has_value());
+ absl::optional<absl::string_view> pem_root_certs_to_report;
+ if (pem_root_certs.has_value() &&
+ watcher_it->second.root_cert_name == cert_name) {
+ // In this case, We've already sent the credential updates at the time
+ // when checking pem_root_certs, so we will skip here.
+ continue;
+ } else if (watcher_it->second.root_cert_name.has_value()) {
+ auto& root_cert_info =
+ certificate_info_map_[*watcher_it->second.root_cert_name];
+ pem_root_certs_to_report = root_cert_info.pem_root_certs;
+ }
+ watcher_ptr->OnCertificatesChanged(pem_root_certs_to_report,
+ pem_key_cert_pairs);
+ }
+ cert_info.pem_key_cert_pairs = std::move(*pem_key_cert_pairs);
+ }
+}
+
+bool grpc_tls_certificate_distributor::HasRootCerts(
+ const std::string& root_cert_name) {
+ grpc_core::MutexLock lock(&mu_);
+ const auto it = certificate_info_map_.find(root_cert_name);
+ return it != certificate_info_map_.end() &&
+ !it->second.pem_root_certs.empty();
+};
+
+bool grpc_tls_certificate_distributor::HasKeyCertPairs(
+ const std::string& identity_cert_name) {
+ grpc_core::MutexLock lock(&mu_);
+ const auto it = certificate_info_map_.find(identity_cert_name);
+ return it != certificate_info_map_.end() &&
+ !it->second.pem_key_cert_pairs.empty();
+};
+
+void grpc_tls_certificate_distributor::SetErrorForCert(
+ const std::string& cert_name, absl::optional<grpc_error*> root_cert_error,
+ absl::optional<grpc_error*> identity_cert_error) {
+ GPR_ASSERT(root_cert_error.has_value() || identity_cert_error.has_value());
+ grpc_core::MutexLock lock(&mu_);
+ CertificateInfo& cert_info = certificate_info_map_[cert_name];
+ if (root_cert_error.has_value()) {
+ for (auto* watcher_ptr : cert_info.root_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ // identity_cert_error_to_report is the error of the identity cert this
+ // watcher is watching, if there is any.
+ grpc_error* identity_cert_error_to_report = GRPC_ERROR_NONE;
+ if (identity_cert_error.has_value() &&
+ watcher_it->second.identity_cert_name == cert_name) {
+ identity_cert_error_to_report = *identity_cert_error;
+ } else if (watcher_it->second.identity_cert_name.has_value()) {
+ auto& identity_cert_info =
+ certificate_info_map_[*watcher_it->second.identity_cert_name];
+ identity_cert_error_to_report = identity_cert_info.identity_cert_error;
+ }
+ watcher_ptr->OnError(GRPC_ERROR_REF(*root_cert_error),
+ GRPC_ERROR_REF(identity_cert_error_to_report));
+ }
+ cert_info.SetRootError(*root_cert_error);
+ }
+ if (identity_cert_error.has_value()) {
+ for (auto* watcher_ptr : cert_info.identity_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ // root_cert_error_to_report is the error of the root cert this watcher is
+ // watching, if there is any.
+ grpc_error* root_cert_error_to_report = GRPC_ERROR_NONE;
+ if (root_cert_error.has_value() &&
+ watcher_it->second.root_cert_name == cert_name) {
+ // In this case, We've already sent the error updates at the time when
+ // checking root_cert_error, so we will skip here.
+ continue;
+ } else if (watcher_it->second.root_cert_name.has_value()) {
+ auto& root_cert_info =
+ certificate_info_map_[*watcher_it->second.root_cert_name];
+ root_cert_error_to_report = root_cert_info.root_cert_error;
+ }
+ watcher_ptr->OnError(GRPC_ERROR_REF(root_cert_error_to_report),
+ GRPC_ERROR_REF(*identity_cert_error));
+ }
+ cert_info.SetIdentityError(*identity_cert_error);
+ }
+};
+
+void grpc_tls_certificate_distributor::SetError(grpc_error* error) {
+ GPR_ASSERT(error != GRPC_ERROR_NONE);
+ grpc_core::MutexLock lock(&mu_);
+ for (const auto& watcher : watchers_) {
+ const auto watcher_ptr = watcher.first;
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto& watcher_info = watcher.second;
+ watcher_ptr->OnError(
+ watcher_info.root_cert_name.has_value() ? GRPC_ERROR_REF(error)
+ : GRPC_ERROR_NONE,
+ watcher_info.identity_cert_name.has_value() ? GRPC_ERROR_REF(error)
+ : GRPC_ERROR_NONE);
+ }
+ for (auto& cert_info_entry : certificate_info_map_) {
+ auto& cert_info = cert_info_entry.second;
+ cert_info.SetRootError(GRPC_ERROR_REF(error));
+ cert_info.SetIdentityError(GRPC_ERROR_REF(error));
+ }
+ GRPC_ERROR_UNREF(error);
+};
+
+void grpc_tls_certificate_distributor::WatchTlsCertificates(
+ std::unique_ptr<TlsCertificatesWatcherInterface> watcher,
+ absl::optional<std::string> root_cert_name,
+ absl::optional<std::string> identity_cert_name) {
+ bool start_watching_root_cert = false;
+ bool already_watching_identity_for_root_cert = false;
+ bool start_watching_identity_cert = false;
+ bool already_watching_root_for_identity_cert = false;
+ GPR_ASSERT(root_cert_name.has_value() || identity_cert_name.has_value());
+ TlsCertificatesWatcherInterface* watcher_ptr = watcher.get();
+ GPR_ASSERT(watcher_ptr != nullptr);
+ // Update watchers_ and certificate_info_map_.
+ {
+ grpc_core::MutexLock lock(&mu_);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ // The caller needs to cancel the watcher first if it wants to re-register
+ // the watcher.
+ GPR_ASSERT(watcher_it == watchers_.end());
+ watchers_[watcher_ptr] = {std::move(watcher), root_cert_name,
+ identity_cert_name};
+ absl::optional<absl::string_view> updated_root_certs;
+ absl::optional<PemKeyCertPairList> updated_identity_pairs;
+ grpc_error* root_error = GRPC_ERROR_NONE;
+ grpc_error* identity_error = GRPC_ERROR_NONE;
+ if (root_cert_name.has_value()) {
+ CertificateInfo& cert_info = certificate_info_map_[*root_cert_name];
+ start_watching_root_cert = cert_info.root_cert_watchers.empty();
+ already_watching_identity_for_root_cert =
+ !cert_info.identity_cert_watchers.empty();
+ cert_info.root_cert_watchers.insert(watcher_ptr);
+ root_error = GRPC_ERROR_REF(cert_info.root_cert_error);
+ // Empty credentials will be treated as no updates.
+ if (!cert_info.pem_root_certs.empty()) {
+ updated_root_certs = cert_info.pem_root_certs;
+ }
+ }
+ if (identity_cert_name.has_value()) {
+ CertificateInfo& cert_info = certificate_info_map_[*identity_cert_name];
+ start_watching_identity_cert = cert_info.identity_cert_watchers.empty();
+ already_watching_root_for_identity_cert =
+ !cert_info.root_cert_watchers.empty();
+ cert_info.identity_cert_watchers.insert(watcher_ptr);
+ identity_error = GRPC_ERROR_REF(cert_info.identity_cert_error);
+ // Empty credentials will be treated as no updates.
+ if (!cert_info.pem_key_cert_pairs.empty()) {
+ updated_identity_pairs = cert_info.pem_key_cert_pairs;
+ }
+ }
+ // Notify this watcher if the certs it is watching already had some
+ // contents. Note that an *_cert_error in cert_info only indicates error
+ // occurred while trying to fetch the latest cert, but the updated_*_certs
+ // should always be valid. So we will send the updates regardless of
+ // *_cert_error.
+ if (updated_root_certs.has_value() || updated_identity_pairs.has_value()) {
+ watcher_ptr->OnCertificatesChanged(updated_root_certs,
+ std::move(updated_identity_pairs));
+ }
+ // Notify this watcher if the certs it is watching already had some errors.
+ if (root_error != GRPC_ERROR_NONE || identity_error != GRPC_ERROR_NONE) {
+ watcher_ptr->OnError(GRPC_ERROR_REF(root_error),
+ GRPC_ERROR_REF(identity_error));
+ }
+ GRPC_ERROR_UNREF(root_error);
+ GRPC_ERROR_UNREF(identity_error);
+ }
+ // Invoke watch status callback if needed.
+ {
+ grpc_core::MutexLock lock(&callback_mu_);
+ if (watch_status_callback_ != nullptr) {
+ if (root_cert_name == identity_cert_name &&
+ (start_watching_root_cert || start_watching_identity_cert)) {
+ watch_status_callback_(*root_cert_name, start_watching_root_cert,
+ start_watching_identity_cert);
+ } else {
+ if (start_watching_root_cert) {
+ watch_status_callback_(*root_cert_name, true,
+ already_watching_identity_for_root_cert);
+ }
+ if (start_watching_identity_cert) {
+ watch_status_callback_(*identity_cert_name,
+ already_watching_root_for_identity_cert, true);
+ }
+ }
+ }
+ }
+};
+
+void grpc_tls_certificate_distributor::CancelTlsCertificatesWatch(
+ TlsCertificatesWatcherInterface* watcher) {
+ absl::optional<std::string> root_cert_name;
+ absl::optional<std::string> identity_cert_name;
+ bool stop_watching_root_cert = false;
+ bool already_watching_identity_for_root_cert = false;
+ bool stop_watching_identity_cert = false;
+ bool already_watching_root_for_identity_cert = false;
+ // Update watchers_ and certificate_info_map_.
+ {
+ grpc_core::MutexLock lock(&mu_);
+ auto it = watchers_.find(watcher);
+ if (it == watchers_.end()) return;
+ WatcherInfo& watcher_info = it->second;
+ root_cert_name = std::move(watcher_info.root_cert_name);
+ identity_cert_name = std::move(watcher_info.identity_cert_name);
+ watchers_.erase(it);
+ if (root_cert_name.has_value()) {
+ auto it = certificate_info_map_.find(*root_cert_name);
+ GPR_ASSERT(it != certificate_info_map_.end());
+ CertificateInfo& cert_info = it->second;
+ cert_info.root_cert_watchers.erase(watcher);
+ stop_watching_root_cert = cert_info.root_cert_watchers.empty();
+ already_watching_identity_for_root_cert =
+ !cert_info.identity_cert_watchers.empty();
+ if (stop_watching_root_cert && !already_watching_identity_for_root_cert) {
+ certificate_info_map_.erase(it);
+ }
+ }
+ if (identity_cert_name.has_value()) {
+ auto it = certificate_info_map_.find(*identity_cert_name);
+ GPR_ASSERT(it != certificate_info_map_.end());
+ CertificateInfo& cert_info = it->second;
+ cert_info.identity_cert_watchers.erase(watcher);
+ stop_watching_identity_cert = cert_info.identity_cert_watchers.empty();
+ already_watching_root_for_identity_cert =
+ !cert_info.root_cert_watchers.empty();
+ if (stop_watching_identity_cert &&
+ !already_watching_root_for_identity_cert) {
+ certificate_info_map_.erase(it);
+ }
+ }
+ }
+ // Invoke watch status callback if needed.
+ {
+ grpc_core::MutexLock lock(&callback_mu_);
+ if (watch_status_callback_ != nullptr) {
+ if (root_cert_name == identity_cert_name &&
+ (stop_watching_root_cert || stop_watching_identity_cert)) {
+ watch_status_callback_(*root_cert_name, !stop_watching_root_cert,
+ !stop_watching_identity_cert);
+ } else {
+ if (stop_watching_root_cert) {
+ watch_status_callback_(*root_cert_name, false,
+ already_watching_identity_for_root_cert);
+ }
+ if (stop_watching_identity_cert) {
+ watch_status_callback_(*identity_cert_name,
+ already_watching_root_for_identity_cert,
+ false);
+ }
+ }
+ }
+ }
+};
diff --git a/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h
new file mode 100644
index 00000000..efc9e33e
--- /dev/null
+++ b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h
@@ -0,0 +1,214 @@
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/grpc_security.h>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/types/optional.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/security/security_connector/ssl_utils.h"
+
+// TLS certificate distributor.
+struct grpc_tls_certificate_distributor
+ : public grpc_core::RefCounted<grpc_tls_certificate_distributor> {
+ public:
+ typedef absl::InlinedVector<grpc_core::PemKeyCertPair, 1> PemKeyCertPairList;
+
+ // Interface for watching TLS certificates update.
+ class TlsCertificatesWatcherInterface {
+ public:
+ virtual ~TlsCertificatesWatcherInterface() = default;
+
+ // Handles the delivery of the updated root and identity certificates.
+ // An absl::nullopt value indicates no corresponding contents for
+ // root_certs or key_cert_pairs. Note that we will send updates of the
+ // latest contents for both root and identity certificates, even when only
+ // one side of it got updated.
+ //
+ // @param root_certs the contents of the reloaded root certs.
+ // @param key_cert_pairs the contents of the reloaded identity key-cert
+ // pairs.
+ virtual void OnCertificatesChanged(
+ absl::optional<absl::string_view> root_certs,
+ absl::optional<PemKeyCertPairList> key_cert_pairs) = 0;
+
+ // Handles an error that occurs while attempting to fetch certificate data.
+ // Note that if a watcher sees an error, it simply means the Provider is
+ // having problems renewing new data. If the watcher has previously received
+ // several OnCertificatesChanged, all the data received from that function
+ // is valid.
+ // In that case, watcher might simply log the error. If the watcher hasn't
+ // received any OnCertificatesChanged before the error occurs, no valid
+ // data is available yet, and the watcher should either fail or "waiting"
+ // for the valid data in a non-blocking way.
+ //
+ // @param root_cert_error the error occurred while reloading root
+ // certificates.
+ // @param identity_cert_error the error occurred while reloading identity
+ // certificates.
+ virtual void OnError(grpc_error* root_cert_error,
+ grpc_error* identity_cert_error) = 0;
+ };
+
+ // Sets the key materials based on their certificate name. Note that we are
+ // not doing any copies for pem_root_certs and pem_key_cert_pairs. For
+ // pem_root_certs, the original string contents need to outlive the
+ // distributor; for pem_key_cert_pairs, internally it is taking two
+ // unique_ptr(s) to the credential string, so the ownership is actually
+ // transferred.
+ //
+ // @param cert_name The name of the certificates being updated.
+ // @param pem_root_certs The content of root certificates.
+ // @param pem_key_cert_pairs The content of identity key-cert pairs.
+ void SetKeyMaterials(const std::string& cert_name,
+ absl::optional<std::string> pem_root_certs,
+ absl::optional<PemKeyCertPairList> pem_key_cert_pairs);
+
+ bool HasRootCerts(const std::string& root_cert_name);
+
+ bool HasKeyCertPairs(const std::string& identity_cert_name);
+
+ // Propagates the error that the caller (e.g. Producer) encounters to all the
+ // watchers watching a particular certificate name.
+ //
+ // @param cert_name The watching cert name of the watchers that the caller
+ // wants to notify when encountering error.
+ // @param root_cert_error The error that the caller encounters when reloading
+ // root certs.
+ // @param identity_cert_error The error that the caller encounters when
+ // reloading identity certs.
+ void SetErrorForCert(const std::string& cert_name,
+ absl::optional<grpc_error*> root_cert_error,
+ absl::optional<grpc_error*> identity_cert_error);
+
+ // Propagates the error that the caller (e.g. Producer) encounters to all
+ // watchers.
+ //
+ // @param error The error that the caller encounters.
+ void SetError(grpc_error* error);
+
+ // Sets the TLS certificate watch status callback function. The
+ // grpc_tls_certificate_distributor will invoke this callback when a new
+ // certificate name is watched by a newly registered watcher, or when a
+ // certificate name is no longer watched by any watchers.
+ // Note that when the callback shows a cert is no longer being watched, the
+ // distributor will delete the corresponding certificate data from its cache,
+ // and clear the corresponding error, if there is any. This means that if the
+ // callback subsequently says the same cert is now being watched again, the
+ // provider must re-provide the credentials or re-invoke the errors to the
+ // distributor, to indicate a successful or failed reloading.
+ // @param callback The callback function being set by the caller, e.g the
+ // Producer. Note that this callback will be invoked for each certificate
+ // name.
+ //
+ // For the parameters in the callback function:
+ // string_value The name of the certificates being watched.
+ // bool_value_1 If the root certificates with the specific name are being
+ // watched. bool_value_2 If the identity certificates with the specific name
+ // are being watched.
+ void SetWatchStatusCallback(
+ std::function<void(std::string, bool, bool)> callback) {
+ grpc_core::MutexLock lock(&mu_);
+ watch_status_callback_ = callback;
+ };
+
+ // Registers a watcher. The caller may keep a raw pointer to the watcher,
+ // which may be used only for cancellation. (Because the caller does not own
+ // the watcher, the pointer must not be used for any other purpose.) At least
+ // one of root_cert_name and identity_cert_name must be specified.
+ //
+ // @param watcher The watcher being registered.
+ // @param root_cert_name The name of the root certificates that will be
+ // watched. If set to absl::nullopt, the root certificates won't be watched.
+ // @param identity_cert_name The name of the identity certificates that will
+ // be watched. If set to absl::nullopt, the identity certificates won't be
+ // watched.
+ void WatchTlsCertificates(
+ std::unique_ptr<TlsCertificatesWatcherInterface> watcher,
+ absl::optional<std::string> root_cert_name,
+ absl::optional<std::string> identity_cert_name);
+
+ // Cancels a watcher.
+ //
+ // @param watcher The watcher being cancelled.
+ void CancelTlsCertificatesWatch(TlsCertificatesWatcherInterface* watcher);
+
+ private:
+ // Contains the information about each watcher.
+ struct WatcherInfo {
+ std::unique_ptr<TlsCertificatesWatcherInterface> watcher;
+ absl::optional<std::string> root_cert_name;
+ absl::optional<std::string> identity_cert_name;
+ };
+ // CertificateInfo contains the credential contents and some additional
+ // watcher information.
+ // Note that having errors doesn't indicate the corresponding credentials are
+ // invalid. For example, if root_cert_error != nullptr but pem_root_certs has
+ // value, it simply means an error occurs while trying to fetch the latest
+ // root certs, while pem_root_certs still contains the valid old data.
+ struct CertificateInfo {
+ // The contents of the root certificates.
+ std::string pem_root_certs;
+ // The contents of the identity key-certificate pairs.
+ PemKeyCertPairList pem_key_cert_pairs;
+ // The root cert reloading error propagated by the caller.
+ grpc_error* root_cert_error = GRPC_ERROR_NONE;
+ // The identity cert reloading error propagated by the caller.
+ grpc_error* identity_cert_error = GRPC_ERROR_NONE;
+ // The set of watchers watching root certificates.
+ // This is mainly used for quickly looking up the affected watchers while
+ // performing a credential reloading.
+ std::set<TlsCertificatesWatcherInterface*> root_cert_watchers;
+ // The set of watchers watching identity certificates. This is mainly used
+ // for quickly looking up the affected watchers while performing a
+ // credential reloading.
+ std::set<TlsCertificatesWatcherInterface*> identity_cert_watchers;
+
+ ~CertificateInfo() {
+ GRPC_ERROR_UNREF(root_cert_error);
+ GRPC_ERROR_UNREF(identity_cert_error);
+ }
+ void SetRootError(grpc_error* error) {
+ GRPC_ERROR_UNREF(root_cert_error);
+ root_cert_error = error;
+ }
+ void SetIdentityError(grpc_error* error) {
+ GRPC_ERROR_UNREF(identity_cert_error);
+ identity_cert_error = error;
+ }
+ };
+
+ grpc_core::Mutex mu_;
+ // We need a dedicated mutex for watch_status_callback_ for allowing
+ // callers(e.g. Producer) to directly set key materials in the callback
+ // functions.
+ grpc_core::Mutex callback_mu_;
+ // Stores information about each watcher.
+ std::map<TlsCertificatesWatcherInterface*, WatcherInfo> watchers_;
+ // The callback to notify the caller, e.g. the Producer, that the watch status
+ // is changed.
+ std::function<void(std::string, bool, bool)> watch_status_callback_;
+ // Stores the names of each certificate, and their corresponding credential
+ // contents as well as some additional watcher information.
+ std::map<std::string, CertificateInfo> certificate_info_map_;
+};
+
+#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
diff --git a/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h b/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
index c411fb2b..52a1218d 100644
--- a/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
+++ b/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
@@ -23,7 +23,8 @@
#include <grpc/grpc_security.h>
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "absl/container/inlined_vector.h"
+
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
@@ -44,8 +45,7 @@ struct grpc_tls_error_details
struct grpc_tls_key_materials_config
: public grpc_core::RefCounted<grpc_tls_key_materials_config> {
public:
- typedef grpc_core::InlinedVector<grpc_core::PemKeyCertPair, 1>
- PemKeyCertPairList;
+ typedef absl::InlinedVector<grpc_core::PemKeyCertPair, 1> PemKeyCertPairList;
/** Getters for member fields. **/
const char* pem_root_certs() const { return pem_root_certs_.get(); }
@@ -264,6 +264,8 @@ struct grpc_tls_credentials_options
grpc_tls_server_verification_option server_verification_option() const {
return server_verification_option_;
}
+ grpc_tls_version min_tls_version() const { return min_tls_version_; }
+ grpc_tls_version max_tls_version() const { return max_tls_version_; }
grpc_tls_key_materials_config* key_materials_config() const {
return key_materials_config_.get();
}
@@ -284,6 +286,12 @@ struct grpc_tls_credentials_options
const grpc_tls_server_verification_option server_verification_option) {
server_verification_option_ = server_verification_option;
}
+ void set_min_tls_version(grpc_tls_version min_tls_version) {
+ min_tls_version_ = min_tls_version;
+ }
+ void set_max_tls_version(grpc_tls_version max_tls_version) {
+ max_tls_version_ = max_tls_version;
+ }
void set_key_materials_config(
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> config) {
key_materials_config_ = std::move(config);
@@ -302,6 +310,8 @@ struct grpc_tls_credentials_options
grpc_ssl_client_certificate_request_type cert_request_type_;
grpc_tls_server_verification_option server_verification_option_ =
GRPC_TLS_SERVER_VERIFICATION;
+ grpc_tls_version min_tls_version_ = grpc_tls_version::TLS1_2;
+ grpc_tls_version max_tls_version_ = grpc_tls_version::TLS1_3;
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> key_materials_config_;
grpc_core::RefCountedPtr<grpc_tls_credential_reload_config>
credential_reload_config_;
diff --git a/grpc/src/core/lib/security/credentials/xds/xds_credentials.cc b/grpc/src/core/lib/security/credentials/xds/xds_credentials.cc
new file mode 100644
index 00000000..682d49ba
--- /dev/null
+++ b/grpc/src/core/lib/security/credentials/xds/xds_credentials.cc
@@ -0,0 +1,45 @@
+//
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/security/credentials/xds/xds_credentials.h"
+
+namespace grpc_core {
+
+constexpr const char XdsCredentials::kCredentialsTypeXds[];
+
+grpc_core::RefCountedPtr<grpc_channel_security_connector>
+XdsCredentials::create_security_connector(
+ grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
+ const char* target_name, const grpc_channel_args* args,
+ grpc_channel_args** new_args) {
+ /* TODO(yashkt) : To be filled */
+ if (fallback_credentials_ != nullptr) {
+ return fallback_credentials_->create_security_connector(
+ std::move(call_creds), target_name, args, new_args);
+ }
+ return nullptr;
+}
+
+} // namespace grpc_core
+
+grpc_channel_credentials* grpc_xds_credentials_create(
+ grpc_channel_credentials* fallback_credentials) {
+ return new grpc_core::XdsCredentials(fallback_credentials->Ref());
+}
diff --git a/grpc/src/core/lib/security/credentials/xds/xds_credentials.h b/grpc/src/core/lib/security/credentials/xds/xds_credentials.h
new file mode 100644
index 00000000..51576dee
--- /dev/null
+++ b/grpc/src/core/lib/security/credentials/xds/xds_credentials.h
@@ -0,0 +1,51 @@
+//
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_XDS_XDS_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_XDS_XDS_CREDENTIALS_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/grpc_security.h>
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+namespace grpc_core {
+
+class XdsCredentials final : public grpc_channel_credentials {
+ public:
+ static constexpr const char kCredentialsTypeXds[] = "Xds";
+
+ explicit XdsCredentials(
+ grpc_core::RefCountedPtr<grpc_channel_credentials> fallback_credentials)
+ : grpc_channel_credentials(kCredentialsTypeXds),
+ fallback_credentials_(std::move(fallback_credentials)) {}
+
+ grpc_core::RefCountedPtr<grpc_channel_security_connector>
+ create_security_connector(
+ grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
+ const char* target_name, const grpc_channel_args* args,
+ grpc_channel_args** new_args) override;
+
+ private:
+ grpc_core::RefCountedPtr<grpc_channel_credentials> fallback_credentials_;
+};
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_XDS_XDS_CREDENTIALS_H */