add experiment

pull/35851/head
Mark D. Roth 1 year ago
parent 3296d34ea6
commit c470bf5e61
  1. 1
      BUILD
  2. 10
      bazel/experiments.bzl
  3. 11
      src/core/client_channel/http_proxy_mapper.cc
  4. 12
      src/core/lib/experiments/experiments.cc
  5. 11
      src/core/lib/experiments/experiments.h
  6. 5
      src/core/lib/experiments/experiments.yaml
  7. 2
      src/core/lib/experiments/rollouts.yaml
  8. 20
      src/core/lib/security/credentials/jwt/json_token.cc
  9. 44
      src/core/lib/security/credentials/jwt/jwt_verifier.cc
  10. 2
      test/core/security/BUILD

@ -3384,6 +3384,7 @@ grpc_cc_library(
"//src/core:arena_promise",
"//src/core:closure",
"//src/core:error",
"//src/core:experiments",
"//src/core:gpr_manual_constructor",
"//src/core:httpcli_ssl_credentials",
"//src/core:iomgr_fwd",

@ -17,6 +17,7 @@
"""Dictionary of tags to experiments so we know when to test different experiments."""
EXPERIMENT_ENABLES = {
"absl_base64": "absl_base64",
"call_status_override_on_cancellation": "call_status_override_on_cancellation",
"call_v3": "call_v3",
"canary_client_privacy": "canary_client_privacy",
@ -124,6 +125,9 @@ EXPERIMENTS = {
"round_robin_delegate_to_pick_first",
"wrr_delegate_to_pick_first",
],
"credential_token_tests": [
"absl_base64",
],
"event_engine_listener_test": [
"event_engine_listener",
],
@ -201,6 +205,9 @@ EXPERIMENTS = {
"round_robin_delegate_to_pick_first",
"wrr_delegate_to_pick_first",
],
"credential_token_tests": [
"absl_base64",
],
"flow_control_test": [
"write_size_cap",
"write_size_policy",
@ -288,6 +295,9 @@ EXPERIMENTS = {
"round_robin_delegate_to_pick_first",
"wrr_delegate_to_pick_first",
],
"credential_token_tests": [
"absl_base64",
],
"event_engine_listener_test": [
"event_engine_listener",
],

@ -46,11 +46,13 @@
#include "src/core/lib/address_utils/parse_address.h"
#include "src/core/lib/address_utils/sockaddr_utils.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/env.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/transport/http_connect_handshaker.h"
#include "src/core/lib/uri/uri_parser.h"
@ -258,7 +260,14 @@ absl::optional<std::string> HttpProxyMapper::MapName(
MaybeAddDefaultPort(absl::StripPrefix(uri->path(), "/")));
if (user_cred.has_value()) {
// Use base64 encoding for user credentials as stated in RFC 7617
std::string encoded_user_cred = absl::Base64Escape(*user_cred);
std::string encoded_user_cred;
if (IsAbslBase64Enabled()) {
encoded_user_cred = absl::Base64Escape(*user_cred);
} else {
UniquePtr<char> tmp(
grpc_base64_encode(user_cred->data(), user_cred->length(), 0, 0));
encoded_user_cred = tmp.get();
}
*args = args->Set(
GRPC_ARG_HTTP_CONNECT_HEADERS,
absl::StrCat("Proxy-Authorization:Basic ", encoded_user_cred));

@ -24,6 +24,8 @@
#if defined(GRPC_CFSTREAM)
namespace {
const char* const description_absl_base64 = "Use abseil base64 functions.";
const char* const additional_constraints_absl_base64 = "{}";
const char* const description_call_status_override_on_cancellation =
"Avoid overriding call status of successfully finished calls if it races "
"with cancellation.";
@ -193,6 +195,8 @@ const bool kDefaultForDebugOnly = true;
namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"absl_base64", description_absl_base64, additional_constraints_absl_base64,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
@ -297,6 +301,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
#elif defined(GPR_WINDOWS)
namespace {
const char* const description_absl_base64 = "Use abseil base64 functions.";
const char* const additional_constraints_absl_base64 = "{}";
const char* const description_call_status_override_on_cancellation =
"Avoid overriding call status of successfully finished calls if it races "
"with cancellation.";
@ -466,6 +472,8 @@ const bool kDefaultForDebugOnly = true;
namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"absl_base64", description_absl_base64, additional_constraints_absl_base64,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
@ -570,6 +578,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
#else
namespace {
const char* const description_absl_base64 = "Use abseil base64 functions.";
const char* const additional_constraints_absl_base64 = "{}";
const char* const description_call_status_override_on_cancellation =
"Avoid overriding call status of successfully finished calls if it races "
"with cancellation.";
@ -739,6 +749,8 @@ const bool kDefaultForDebugOnly = true;
namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"absl_base64", description_absl_base64, additional_constraints_absl_base64,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,

@ -57,6 +57,8 @@ namespace grpc_core {
#ifdef GRPC_EXPERIMENTS_ARE_FINAL
#if defined(GRPC_CFSTREAM)
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() { return true; }
#ifndef NDEBUG
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
#endif
@ -119,6 +121,8 @@ inline bool IsWriteSizeCapEnabled() { return true; }
inline bool IsWrrDelegateToPickFirstEnabled() { return true; }
#elif defined(GPR_WINDOWS)
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() { return true; }
#ifndef NDEBUG
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
#endif
@ -182,6 +186,8 @@ inline bool IsWriteSizeCapEnabled() { return true; }
inline bool IsWrrDelegateToPickFirstEnabled() { return true; }
#else
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() { return true; }
#ifndef NDEBUG
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
#endif
@ -247,6 +253,7 @@ inline bool IsWrrDelegateToPickFirstEnabled() { return true; }
#else
enum ExperimentIds {
kExperimentIdAbslBase64,
kExperimentIdCallStatusOverrideOnCancellation,
kExperimentIdCallV3,
kExperimentIdCanaryClientPrivacy,
@ -289,6 +296,10 @@ enum ExperimentIds {
kExperimentIdWrrDelegateToPickFirst,
kNumExperiments
};
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() {
return IsExperimentEnabled(kExperimentIdAbslBase64);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
inline bool IsCallStatusOverrideOnCancellationEnabled() {
return IsExperimentEnabled(kExperimentIdCallStatusOverrideOnCancellation);

@ -40,6 +40,11 @@
# This file only defines the experiments. Refer to rollouts.yaml for the rollout
# state of each experiment.
- name: absl_base64
description: Use abseil base64 functions.
expiry: 2024/06/01
owner: roth@google.com
test_tags: ["credential_token_tests"]
- name: call_status_override_on_cancellation
description:
Avoid overriding call status of successfully finished calls if it races with

@ -40,6 +40,8 @@
#
# Supported platforms: ios, windows, posix
- name: absl_base64
default: true
- name: call_status_override_on_cancellation
default: debug
- name: call_v3

@ -42,10 +42,12 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json_reader.h"
#include "src/core/lib/json/json_writer.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/slice/b64.h"
using grpc_core::Json;
@ -181,6 +183,9 @@ static char* encoded_jwt_header(const char* key_id, const char* algorithm) {
{"kid", Json::FromString(key_id)},
});
std::string json_str = grpc_core::JsonDump(json);
if (!grpc_core::IsAbslBase64Enabled()) {
return grpc_base64_encode(json_str.c_str(), json_str.size(), 1, 0);
}
return gpr_strdup(absl::WebSafeBase64Escape(json_str).c_str());
}
@ -209,6 +214,9 @@ static char* encoded_jwt_claim(const grpc_auth_json_key* json_key,
std::string json_str =
grpc_core::JsonDump(Json::FromObject(std::move(object)));
if (!grpc_core::IsAbslBase64Enabled()) {
return grpc_base64_encode(json_str.c_str(), json_str.size(), 1, 0);
}
return gpr_strdup(absl::WebSafeBase64Escape(json_str).c_str());
}
@ -281,10 +289,14 @@ char* compute_and_encode_signature(const grpc_auth_json_key* json_key,
gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed.");
goto end;
}
result =
gpr_strdup(absl::WebSafeBase64Escape(
absl::string_view(reinterpret_cast<char*>(sig), sig_len))
.c_str());
if (!grpc_core::IsAbslBase64Enabled()) {
result = grpc_base64_encode(sig, sig_len, 1, 0);
} else {
result =
gpr_strdup(absl::WebSafeBase64Escape(
absl::string_view(reinterpret_cast<char*>(sig), sig_len))
.c_str());
}
end:
#if OPENSSL_VERSION_NUMBER < 0x30000000L

@ -53,6 +53,7 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/gprpp/memory.h"
@ -67,6 +68,7 @@
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/json/json_reader.h"
#include "src/core/lib/security/credentials/credentials.h" // IWYU pragma: keep
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/uri/uri_parser.h"
@ -112,9 +114,19 @@ static const EVP_MD* evp_md_from_alg(const char* alg) {
static Json parse_json_part_from_jwt(const char* str, size_t len) {
std::string string;
if (!absl::WebSafeBase64Unescape(absl::string_view(str, len), &string)) {
gpr_log(GPR_ERROR, "Invalid base64.");
return Json(); // JSON null
if (!grpc_core::IsAbslBase64Enabled()) {
grpc_slice slice = grpc_base64_decode_with_len(str, len, 1);
if (GRPC_SLICE_IS_EMPTY(slice)) {
gpr_log(GPR_ERROR, "Invalid base64.");
return Json(); // JSON null
}
string = std::string(grpc_core::StringViewFromSlice(slice));
grpc_core::CSliceUnref(slice);
} else {
if (!absl::WebSafeBase64Unescape(absl::string_view(str, len), &string)) {
gpr_log(GPR_ERROR, "Invalid base64.");
return Json(); // JSON null
}
}
auto json = grpc_core::JsonParse(string);
if (!json.ok()) {
@ -479,6 +491,18 @@ end:
static BIGNUM* bignum_from_base64(const char* b64) {
if (b64 == nullptr) return nullptr;
if (!grpc_core::IsAbslBase64Enabled()) {
grpc_slice bin = grpc_base64_decode(b64, 1);
if (GRPC_SLICE_IS_EMPTY(bin)) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
return nullptr;
}
BIGNUM* result =
BN_bin2bn(GRPC_SLICE_START_PTR(bin),
TSI_SIZE_AS_SIZE(GRPC_SLICE_LENGTH(bin)), nullptr);
grpc_core::CSliceUnref(bin);
return result;
}
std::string string;
if (!absl::WebSafeBase64Unescape(b64, &string)) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
@ -920,10 +944,10 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier* verifier,
const char* dot = nullptr;
jose_header* header = nullptr;
grpc_jwt_claims* claims = nullptr;
grpc_slice signature;
size_t signed_jwt_len;
const char* cur = jwt;
Json json;
std::string signature;
GPR_ASSERT(verifier != nullptr && jwt != nullptr && audience != nullptr &&
cb != nullptr);
@ -945,11 +969,17 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier* verifier,
signed_jwt_len = static_cast<size_t>(dot - jwt);
cur = dot + 1;
if (!absl::WebSafeBase64Unescape(cur, &signature)) goto error;
if (!grpc_core::IsAbslBase64Enabled()) {
signature = grpc_base64_decode(cur, 1);
if (GRPC_SLICE_IS_EMPTY(signature)) goto error;
} else {
std::string signature_str;
if (!absl::WebSafeBase64Unescape(cur, &signature_str)) goto error;
signature = grpc_slice_from_cpp_string(std::move(signature_str));
}
retrieve_key_and_verify(
verifier_cb_ctx_create(verifier, pollset, header, claims, audience,
grpc_slice_from_cpp_string(std::move(signature)),
jwt, signed_jwt_len, user_data, cb));
signature, jwt, signed_jwt_len, user_data, cb));
return;
error:

@ -140,6 +140,7 @@ grpc_cc_test(
language = "C++",
uses_event_engine = False,
uses_polling = False,
tags = ["credential_token_tests"],
deps = [
"//:gpr",
"//:grpc",
@ -156,6 +157,7 @@ grpc_cc_test(
language = "C++",
uses_event_engine = False,
uses_polling = False,
tags = ["credential_token_tests"],
deps = [
"//:gpr",
"//:grpc",

Loading…
Cancel
Save