Allow to specify user provided audience in google default credentials and JWT credentials (#26456)

* support user provided audience in gdc and jwt
reviewable/pr26471/r1
ZhenLian 4 years ago committed by GitHub
parent 39d007e83b
commit 5a91a513fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      include/grpc/grpc_security.h
  2. 15
      include/grpcpp/security/credentials.h
  3. 2
      src/core/ext/xds/xds_bootstrap.cc
  4. 18
      src/core/lib/security/credentials/google_default/google_default_credentials.cc
  5. 43
      src/core/lib/security/credentials/jwt/jwt_credentials.cc
  6. 17
      src/core/lib/security/credentials/jwt/jwt_credentials.h
  7. 15
      src/cpp/client/secure_credentials.cc
  8. 2
      src/php/ext/grpc/channel_credentials.c
  9. 2
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
  10. 4
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  11. 4
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  12. 129
      test/core/security/credentials_test.cc

@ -159,9 +159,18 @@ GRPCAPI void grpc_channel_credentials_release(grpc_channel_credentials* creds);
If nullptr is supplied, the returned channel credentials object will use a
call credentials object based on the Application Default Credentials
mechanism.
user_provided_audience is an optional field for user to override the
audience in the JWT token if used. If user_provided_audience is nullptr,
the service URL will be used as the audience. Note that
user_provided_audience will only be used if a service account JWT access
credential is created by the application default credentials mechanism. Also
note that user_provided_audience will be ignored if the call_credentials is
not nullptr.
*/
GRPCAPI grpc_channel_credentials* grpc_google_default_credentials_create(
grpc_call_credentials* call_credentials);
grpc_call_credentials* call_credentials,
const char* user_provided_audience);
/** Callback for getting the SSL roots override from the application.
In case of success, *pem_roots_certs must be set to a NULL terminated string
@ -324,11 +333,14 @@ GRPCAPI gpr_timespec grpc_max_auth_token_lifetime(void);
- json_key is the JSON key string containing the client's private key.
- token_lifetime is the lifetime of each Json Web Token (JWT) created with
this credentials. It should not exceed grpc_max_auth_token_lifetime or
will be cropped to this value. */
will be cropped to this value.
- user_provided_audience is an optional field for user to override the
auidence in the JWT token. If user_provided_audience is nullptr, the
service URL will be used as the audience. */
GRPCAPI grpc_call_credentials*
grpc_service_account_jwt_access_credentials_create(const char* json_key,
gpr_timespec token_lifetime,
void* reserved);
grpc_service_account_jwt_access_credentials_create(
const char* json_key, gpr_timespec token_lifetime,
const char* user_provided_audience);
/** Builds External Account credentials.
- json_string is the JSON string containing the credentials options.

@ -172,11 +172,18 @@ struct SslCredentialsOptions {
/// Builds credentials with reasonable defaults.
///
/// user_provided_audience is an optional field for user to override the
/// auidence in the JWT token. If user_provided_audience is empty, the service
/// URL will be used as the audience. Note that user_provided_audience will
/// only be used if a service account JWT access credential is created by
/// the application default credentials mechanism.
///
/// \warning Only use these credentials when connecting to a Google endpoint.
/// Using these credentials to connect to any other service may result in this
/// service being able to impersonate your client for requests to Google
/// services.
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials();
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials(
const grpc::string& user_provided_audience = "");
/// Builds SSL Credentials given SSL specific options
std::shared_ptr<ChannelCredentials> SslCredentials(
@ -197,9 +204,13 @@ constexpr long kMaxAuthTokenLifetimeSecs = 3600;
/// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
/// (JWT) created with this credentials. It should not exceed
/// \a kMaxAuthTokenLifetimeSecs or will be cropped to this value.
/// user_provided_audience is an optional field for user to override the
/// auidence in the JWT token. If user_provided_audience is empty, the service
/// URL will be used as the audience.
std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key,
long token_lifetime_seconds = kMaxAuthTokenLifetimeSecs);
long token_lifetime_seconds = kMaxAuthTokenLifetimeSecs,
const grpc::string& user_provided_audience = "");
/// Builds refresh token credentials.
/// json_refresh_token is the JSON string containing the refresh token along

@ -59,7 +59,7 @@ RefCountedPtr<grpc_channel_credentials>
XdsChannelCredsRegistry::MakeChannelCreds(const std::string& creds_type,
const Json& /*config*/) {
if (creds_type == "google_default") {
return grpc_google_default_credentials_create(nullptr);
return grpc_google_default_credentials_create(nullptr, nullptr);
} else if (creds_type == "insecure") {
return grpc_insecure_credentials_create();
} else if (creds_type == "fake") {

@ -224,7 +224,7 @@ static int is_metadata_server_reachable() {
/* Takes ownership of creds_path if not NULL. */
static grpc_error_handle create_default_creds_from_path(
const std::string& creds_path,
const std::string& creds_path, const char* user_provided_audience,
grpc_core::RefCountedPtr<grpc_call_credentials>* creds) {
grpc_auth_json_key key;
grpc_auth_refresh_token token;
@ -250,9 +250,10 @@ static grpc_error_handle create_default_creds_from_path(
/* First, try an auth json key. */
key = grpc_auth_json_key_create_from_json(json);
if (grpc_auth_json_key_is_valid(&key)) {
if (user_provided_audience == nullptr) user_provided_audience = "";
result =
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
key, grpc_max_auth_token_lifetime());
key, grpc_max_auth_token_lifetime(), user_provided_audience);
if (result == nullptr) {
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"grpc_service_account_jwt_access_credentials_create_from_auth_json_"
@ -306,14 +307,15 @@ static bool metadata_server_available() {
}
static grpc_core::RefCountedPtr<grpc_call_credentials> make_default_call_creds(
grpc_error_handle* error) {
const char* user_provided_audience, grpc_error_handle* error) {
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds;
grpc_error_handle 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);
err = create_default_creds_from_path(path_from_env, user_provided_audience,
&call_creds);
gpr_free(path_from_env);
if (err == GRPC_ERROR_NONE) return call_creds;
*error = grpc_error_add_child(*error, err);
@ -321,7 +323,8 @@ static grpc_core::RefCountedPtr<grpc_call_credentials> make_default_call_creds(
/* Then the well-known file. */
err = create_default_creds_from_path(
grpc_get_well_known_google_credentials_file_path(), &call_creds);
grpc_get_well_known_google_credentials_file_path(),
user_provided_audience, &call_creds);
if (err == GRPC_ERROR_NONE) return call_creds;
*error = grpc_error_add_child(*error, err);
@ -343,7 +346,8 @@ static grpc_core::RefCountedPtr<grpc_call_credentials> make_default_call_creds(
}
grpc_channel_credentials* grpc_google_default_credentials_create(
grpc_call_credentials* call_credentials) {
grpc_call_credentials* call_credentials,
const char* user_provided_audience) {
grpc_channel_credentials* result = nullptr;
grpc_core::RefCountedPtr<grpc_call_credentials> call_creds(call_credentials);
grpc_error_handle error = GRPC_ERROR_NONE;
@ -353,7 +357,7 @@ grpc_channel_credentials* grpc_google_default_credentials_create(
(call_credentials));
if (call_creds == nullptr) {
call_creds = make_default_call_creds(&error);
call_creds = make_default_call_creds(user_provided_audience, &error);
}
if (call_creds != nullptr) {

@ -42,10 +42,7 @@ using grpc_core::Json;
void grpc_service_account_jwt_access_credentials::reset_cache() {
GRPC_MDELEM_UNREF(cached_.jwt_md);
cached_.jwt_md = GRPC_MDNULL;
if (cached_.service_url != nullptr) {
gpr_free(cached_.service_url);
cached_.service_url = nullptr;
}
cached_.audience.clear();
cached_.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
}
@ -62,13 +59,14 @@ bool grpc_service_account_jwt_access_credentials::get_request_metadata(
grpc_closure* /*on_request_metadata*/, grpc_error_handle* error) {
gpr_timespec refresh_threshold = gpr_time_from_seconds(
GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
absl::string_view audience = user_provided_audience_.empty()
? absl::string_view(context.service_url)
: user_provided_audience_;
/* See if we can return a cached jwt. */
grpc_mdelem jwt_md = GRPC_MDNULL;
{
gpr_mu_lock(&cache_mu_);
if (cached_.service_url != nullptr &&
strcmp(cached_.service_url, context.service_url) == 0 &&
if (!cached_.audience.empty() && cached_.audience == audience &&
!GRPC_MDISNULL(cached_.jwt_md) &&
(gpr_time_cmp(
gpr_time_sub(cached_.jwt_expiration, gpr_now(GPR_CLOCK_REALTIME)),
@ -83,14 +81,14 @@ bool grpc_service_account_jwt_access_credentials::get_request_metadata(
/* Generate a new jwt. */
gpr_mu_lock(&cache_mu_);
reset_cache();
jwt = grpc_jwt_encode_and_sign(&key_, context.service_url, jwt_lifetime_,
jwt = grpc_jwt_encode_and_sign(&key_, audience.data(), jwt_lifetime_,
nullptr);
if (jwt != nullptr) {
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_.audience = std::string(audience);
cached_.jwt_md = grpc_mdelem_from_slices(
grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
grpc_slice_from_cpp_string(std::move(md_value)));
@ -114,9 +112,12 @@ void grpc_service_account_jwt_access_credentials::cancel_get_request_metadata(
}
grpc_service_account_jwt_access_credentials::
grpc_service_account_jwt_access_credentials(grpc_auth_json_key key,
gpr_timespec token_lifetime)
: grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_JWT), key_(key) {
grpc_service_account_jwt_access_credentials(
grpc_auth_json_key key, gpr_timespec token_lifetime,
std::string user_provided_audience)
: grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_JWT),
key_(key),
user_provided_audience_(std::move(user_provided_audience)) {
gpr_timespec max_token_lifetime = grpc_max_auth_token_lifetime();
if (gpr_time_cmp(token_lifetime, max_token_lifetime) > 0) {
gpr_log(GPR_INFO,
@ -131,13 +132,14 @@ grpc_service_account_jwt_access_credentials::
grpc_core::RefCountedPtr<grpc_call_credentials>
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key key, gpr_timespec token_lifetime) {
grpc_auth_json_key key, gpr_timespec token_lifetime,
std::string user_provided_audience) {
if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return nullptr;
}
return grpc_core::MakeRefCounted<grpc_service_account_jwt_access_credentials>(
key, token_lifetime);
key, token_lifetime, std::move(user_provided_audience));
}
static char* redact_private_key(const char* json_key) {
@ -152,7 +154,8 @@ static char* redact_private_key(const char* json_key) {
}
grpc_call_credentials* grpc_service_account_jwt_access_credentials_create(
const char* json_key, gpr_timespec token_lifetime, void* reserved) {
const char* json_key, gpr_timespec token_lifetime,
const char* user_provided_audience) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace)) {
char* clean_json = redact_private_key(json_key);
gpr_log(GPR_INFO,
@ -161,15 +164,17 @@ grpc_call_credentials* grpc_service_account_jwt_access_credentials_create(
"token_lifetime="
"gpr_timespec { tv_sec: %" PRId64
", tv_nsec: %d, clock_type: %d }, "
"reserved=%p)",
"user_provided_audience=%s)",
clean_json, token_lifetime.tv_sec, token_lifetime.tv_nsec,
static_cast<int>(token_lifetime.clock_type), reserved);
static_cast<int>(token_lifetime.clock_type),
user_provided_audience);
gpr_free(clean_json);
}
GPR_ASSERT(reserved == nullptr);
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
grpc_core::ExecCtx exec_ctx;
if (user_provided_audience == nullptr) user_provided_audience = "";
return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key_create_from_string(json_key), token_lifetime)
grpc_auth_json_key_create_from_string(json_key), token_lifetime,
user_provided_audience)
.release();
}

@ -33,8 +33,9 @@
class grpc_service_account_jwt_access_credentials
: public grpc_call_credentials {
public:
grpc_service_account_jwt_access_credentials(grpc_auth_json_key key,
gpr_timespec token_lifetime);
grpc_service_account_jwt_access_credentials(
grpc_auth_json_key key, gpr_timespec token_lifetime,
std::string user_provided_audience);
~grpc_service_account_jwt_access_credentials() override;
bool get_request_metadata(grpc_polling_entity* pollent,
@ -48,7 +49,9 @@ class grpc_service_account_jwt_access_credentials
const gpr_timespec& jwt_lifetime() const { return jwt_lifetime_; }
const grpc_auth_json_key& key() const { return key_; }
const std::string& user_provided_audience() const {
return user_provided_audience_;
}
std::string debug_string() override {
return absl::StrFormat(
"JWTAccessCredentials{ExpirationTime:%s}",
@ -60,22 +63,24 @@ class grpc_service_account_jwt_access_credentials
void reset_cache();
// 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.
// the audience for a more sophisticated one.
gpr_mu cache_mu_;
struct {
grpc_mdelem jwt_md = GRPC_MDNULL;
char* service_url = nullptr;
std::string audience;
gpr_timespec jwt_expiration;
} cached_;
grpc_auth_json_key key_;
gpr_timespec jwt_lifetime_;
std::string user_provided_audience_;
};
// Private constructor for jwt credentials from an already parsed json key.
// Takes ownership of the key.
grpc_core::RefCountedPtr<grpc_call_credentials>
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key key, gpr_timespec token_lifetime);
grpc_auth_json_key key, gpr_timespec token_lifetime,
std::string user_provided_audience);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H */

@ -103,10 +103,14 @@ std::shared_ptr<CallCredentials> WrapCallCredentials(
}
} // namespace
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials(
const grpc::string& user_provided_audience) {
grpc::GrpcLibraryCodegen init; // To call grpc_init().
return internal::WrapChannelCredentials(
grpc_google_default_credentials_create(nullptr));
grpc_google_default_credentials_create(
nullptr, user_provided_audience.empty()
? nullptr
: user_provided_audience.c_str()));
}
std::shared_ptr<CallCredentials> ExternalAccountCredentials(
@ -320,7 +324,8 @@ std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
// Builds JWT credentials.
std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
const std::string& json_key, long token_lifetime_seconds) {
const std::string& json_key, long token_lifetime_seconds,
const grpc::string& user_provided_audience) {
grpc::GrpcLibraryCodegen init; // To call grpc_init().
if (token_lifetime_seconds <= 0) {
gpr_log(GPR_ERROR,
@ -330,7 +335,9 @@ std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
gpr_timespec lifetime =
gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN);
return WrapCallCredentials(grpc_service_account_jwt_access_credentials_create(
json_key.c_str(), lifetime, nullptr));
json_key.c_str(), lifetime,
user_provided_audience.empty() ? nullptr
: user_provided_audience.c_str()));
}
// Builds refresh token credentials.

@ -131,7 +131,7 @@ PHP_METHOD(ChannelCredentials, invalidateDefaultRootsPem) {
* @return ChannelCredentials The new default channel credentials object
*/
PHP_METHOD(ChannelCredentials, createDefault) {
grpc_channel_credentials *creds = grpc_google_default_credentials_create(NULL);
grpc_channel_credentials *creds = grpc_google_default_credentials_create(NULL, NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, NULL, false
TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);

@ -434,7 +434,7 @@ cdef class ComputeEngineChannelCredentials(ChannelCredentials):
raise ValueError("Call credentials may not be NULL.")
cdef grpc_channel_credentials *c(self) except *:
self._c_creds = grpc_google_default_credentials_create(self._call_creds)
self._c_creds = grpc_google_default_credentials_create(self._call_creds, NULL)
return self._c_creds

@ -525,7 +525,7 @@ cdef extern from "grpc/grpc_security.h":
void grpc_set_ssl_roots_override_callback(
grpc_ssl_roots_override_callback cb) nogil
grpc_channel_credentials *grpc_google_default_credentials_create(grpc_call_credentials* call_credentials) nogil
grpc_channel_credentials *grpc_google_default_credentials_create(grpc_call_credentials* call_credentials, const char *user_provided_audience) nogil
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
verify_peer_options *verify_options, void *reserved) nogil
@ -551,7 +551,7 @@ cdef extern from "grpc/grpc_security.h":
void *reserved) nogil
grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
const char *json_key,
gpr_timespec token_lifetime, void *reserved) nogil
gpr_timespec token_lifetime, const char* user_provided_audience) nogil
grpc_call_credentials *grpc_google_refresh_token_credentials_create(
const char *json_refresh_token, void *reserved) nogil
grpc_call_credentials *grpc_google_iam_credentials_create(

@ -353,7 +353,7 @@ extern grpc_call_credentials_release_type grpc_call_credentials_release_import;
typedef void(*grpc_channel_credentials_release_type)(grpc_channel_credentials* creds);
extern grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
#define grpc_channel_credentials_release grpc_channel_credentials_release_import
typedef grpc_channel_credentials*(*grpc_google_default_credentials_create_type)(grpc_call_credentials* call_credentials);
typedef grpc_channel_credentials*(*grpc_google_default_credentials_create_type)(grpc_call_credentials* call_credentials, const char* user_provided_audience);
extern grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
#define grpc_google_default_credentials_create grpc_google_default_credentials_create_import
typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb);
@ -377,7 +377,7 @@ extern grpc_google_compute_engine_credentials_create_type grpc_google_compute_en
typedef gpr_timespec(*grpc_max_auth_token_lifetime_type)(void);
extern grpc_max_auth_token_lifetime_type grpc_max_auth_token_lifetime_import;
#define grpc_max_auth_token_lifetime grpc_max_auth_token_lifetime_import
typedef grpc_call_credentials*(*grpc_service_account_jwt_access_credentials_create_type)(const char* json_key, gpr_timespec token_lifetime, void* reserved);
typedef grpc_call_credentials*(*grpc_service_account_jwt_access_credentials_create_type)(const char* json_key, gpr_timespec token_lifetime, const char* user_provided_audience);
extern grpc_service_account_jwt_access_credentials_create_type grpc_service_account_jwt_access_credentials_create_import;
#define grpc_service_account_jwt_access_credentials_create grpc_service_account_jwt_access_credentials_create_import
typedef grpc_call_credentials*(*grpc_external_account_credentials_create_type)(const char* json_string, const char* scopes_string);

@ -129,6 +129,9 @@ static const char test_signed_jwt_token_type[] =
static const char test_signed_jwt2[] =
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM5YW"
"U2MDcyZTViYTdnZDkwODg5YzcifQ";
static const char test_signed_jwt3[] =
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM6YW"
"U3MDcyZTViYTdnZDkwODg5YzcifQ";
static const char test_signed_jwt_token_type2[] =
"urn:ietf:params:oauth:token-type:jwt";
static const char test_signed_jwt_path_prefix[] = "test_sign_jwt";
@ -136,6 +139,8 @@ static const char test_signed_jwt_path_prefix[] = "test_sign_jwt";
static const char test_service_url[] = "https://foo.com/foo.v1";
static const char other_test_service_url[] = "https://bar.com/bar.v1";
static const char test_user_provided_audience[] = "https://baz.com/baz.v2";
static const char test_sts_endpoint_url[] =
"https://foo.com:5555/v1/token-exchange";
@ -1296,6 +1301,16 @@ static char* encode_and_sign_jwt_success(const grpc_auth_json_key* json_key,
return gpr_strdup(test_signed_jwt);
}
static char* encode_and_sign_jwt_user_provided_audience_success(
const grpc_auth_json_key* json_key, const char* audience,
gpr_timespec token_lifetime, const char* scope) {
if (strcmp(audience, test_user_provided_audience) == 0) {
validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime);
return gpr_strdup(test_signed_jwt3);
}
return nullptr;
}
static char* encode_and_sign_jwt_failure(const grpc_auth_json_key* json_key,
const char* /*audience*/,
gpr_timespec token_lifetime,
@ -1408,6 +1423,56 @@ static void test_jwt_creds_success(void) {
grpc_jwt_encode_and_sign_set_override(nullptr);
}
static void test_jwt_creds_user_provided_audience_success(void) {
const char expected_creds_debug_string_prefix[] =
"JWTAccessCredentials{ExpirationTime:";
char* json_key_string = test_json_key_str();
grpc_core::ExecCtx exec_ctx;
grpc_auth_metadata_context auth_md_ctx = {test_user_provided_audience,
test_method, nullptr, nullptr};
std::string expected_md_value = absl::StrCat("Bearer ", test_signed_jwt3);
expected_md emd[] = {{"authorization", expected_md_value.c_str()}};
grpc_call_credentials* creds =
grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime(),
test_user_provided_audience);
/* First request: jwt_encode_and_sign should be called. */
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_user_provided_audience_success);
run_request_metadata_test(creds, auth_md_ctx, state);
grpc_core::ExecCtx::Get()->Flush();
/* Second request: the cached token should be served directly. */
state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_should_not_be_called);
run_request_metadata_test(creds, auth_md_ctx, state);
grpc_core::ExecCtx::Get()->Flush();
/* Third request: If service url is provided, it should keep using
* user_provided_audience and the cached token should be served.
*/
state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
auth_md_ctx.service_url = test_service_url;
grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_should_not_be_called);
run_request_metadata_test(creds, auth_md_ctx, state);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
creds->debug_string().c_str(),
strlen(expected_creds_debug_string_prefix)) == 0);
creds->Unref();
gpr_free(json_key_string);
grpc_jwt_encode_and_sign_set_override(nullptr);
}
static void test_jwt_creds_signing_failure(void) {
const char expected_creds_debug_string_prefix[] =
"JWTAccessCredentials{ExpirationTime:";
@ -1464,7 +1529,7 @@ static void test_google_default_creds_auth_key(void) {
"json_key_google_default_creds", json_key);
gpr_free(json_key);
creds = reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(nullptr));
grpc_google_default_credentials_create(nullptr, nullptr));
auto* default_creds =
reinterpret_cast<const grpc_google_default_channel_credentials*>(
creds->inner_creds());
@ -1488,7 +1553,7 @@ static void test_google_default_creds_refresh_token(void) {
set_google_default_creds_env_var_with_file_contents(
"refresh_token_google_default_creds", test_refresh_token_str);
creds = reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(nullptr));
grpc_google_default_credentials_create(nullptr, nullptr));
auto* default_creds =
reinterpret_cast<const grpc_google_default_channel_credentials*>(
creds->inner_creds());
@ -1539,7 +1604,7 @@ static void test_google_default_creds_gce(void) {
/* Simulate a successful detection of GCE. */
grpc_composite_channel_credentials* creds =
reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(nullptr));
grpc_google_default_credentials_create(nullptr, nullptr));
/* Verify that the default creds actually embeds a GCE creds. */
GPR_ASSERT(creds != nullptr);
@ -1557,6 +1622,49 @@ static void test_google_default_creds_gce(void) {
grpc_override_well_known_credentials_path_getter(nullptr);
}
static void test_google_default_creds_user_provided_audience(void) {
grpc_core::ExecCtx exec_ctx;
grpc_composite_channel_credentials* creds;
char* json_key = test_json_key_str();
grpc_flush_cached_google_default_credentials();
set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
g_test_gce_tenancy_checker_called = false;
g_test_is_on_gce = true;
set_google_default_creds_env_var_with_file_contents(
"json_key_google_default_creds", json_key);
gpr_free(json_key);
creds = reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(nullptr,
test_user_provided_audience));
auto* default_creds =
reinterpret_cast<const grpc_google_default_channel_credentials*>(
creds->inner_creds());
GPR_ASSERT(default_creds->ssl_creds() != nullptr);
grpc_auth_metadata_context auth_md_ctx = {test_user_provided_audience,
test_method, nullptr, nullptr};
std::string expected_md_value = absl::StrCat("Bearer ", test_signed_jwt3);
expected_md emd[] = {{"authorization", expected_md_value.c_str()}};
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_user_provided_audience_success);
run_request_metadata_test(
const_cast<grpc_call_credentials*>(creds->call_creds()), auth_md_ctx,
state);
grpc_core::ExecCtx::Get()->Flush();
auto* jwt =
reinterpret_cast<const grpc_service_account_jwt_access_credentials*>(
creds->call_creds());
GPR_ASSERT(
strcmp(jwt->key().client_id,
"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
0);
GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
creds->Unref();
gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
}
static void test_google_default_creds_non_gce(void) {
grpc_core::ExecCtx exec_ctx;
expected_md emd[] = {
@ -1578,7 +1686,7 @@ static void test_google_default_creds_non_gce(void) {
httpcli_post_should_not_be_called);
grpc_composite_channel_credentials* creds =
reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(nullptr));
grpc_google_default_credentials_create(nullptr, nullptr));
/* Verify that the default creds actually embeds a GCE creds. */
GPR_ASSERT(creds != nullptr);
GPR_ASSERT(creds->call_creds() != nullptr);
@ -1616,10 +1724,12 @@ static void test_no_google_default_creds(void) {
default_creds_gce_detection_httpcli_get_failure_override,
httpcli_post_should_not_be_called);
/* Simulate a successful detection of GCE. */
GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
GPR_ASSERT(grpc_google_default_credentials_create(nullptr, nullptr) ==
nullptr);
/* Try a second one. GCE detection should occur again. */
g_test_gce_tenancy_checker_called = false;
GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
GPR_ASSERT(grpc_google_default_credentials_create(nullptr, nullptr) ==
nullptr);
GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
/* Cleanup. */
grpc_override_well_known_credentials_path_getter(nullptr);
@ -1645,7 +1755,7 @@ static void test_google_default_creds_call_creds_specified(void) {
httpcli_post_should_not_be_called);
grpc_composite_channel_credentials* channel_creds =
reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(call_creds));
grpc_google_default_credentials_create(call_creds, nullptr));
GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
GPR_ASSERT(channel_creds != nullptr);
GPR_ASSERT(channel_creds->call_creds() != nullptr);
@ -1704,7 +1814,8 @@ static void test_google_default_creds_not_default(void) {
httpcli_post_should_not_be_called);
grpc_composite_channel_credentials* channel_creds =
reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create(call_creds.release()));
grpc_google_default_credentials_create(call_creds.release(),
nullptr));
GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
GPR_ASSERT(channel_creds != nullptr);
GPR_ASSERT(channel_creds->call_creds() != nullptr);
@ -3390,12 +3501,14 @@ int main(int argc, char** argv) {
test_sts_creds_token_file_not_found();
test_jwt_creds_lifetime();
test_jwt_creds_success();
test_jwt_creds_user_provided_audience_success();
test_jwt_creds_signing_failure();
test_google_default_creds_auth_key();
test_google_default_creds_refresh_token();
test_google_default_creds_gce();
test_google_default_creds_non_gce();
test_no_google_default_creds();
test_google_default_creds_user_provided_audience();
test_google_default_creds_call_creds_specified();
test_google_default_creds_not_default();
test_metadata_plugin_success();

Loading…
Cancel
Save