From 18ffe21abd78dfc4e8b73897789e24e63e8d5723 Mon Sep 17 00:00:00 2001 From: Chuan Ren Date: Mon, 14 Dec 2020 12:17:21 -0800 Subject: [PATCH] Add support of url with query params to url creds --- .../url_external_account_credentials.cc | 8 ++- .../url_external_account_credentials.h | 1 + test/core/security/credentials_test.cc | 50 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/core/lib/security/credentials/external/url_external_account_credentials.cc b/src/core/lib/security/credentials/external/url_external_account_credentials.cc index af02a17ed9d..76f50db53dc 100644 --- a/src/core/lib/security/credentials/external/url_external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/url_external_account_credentials.cc @@ -17,7 +17,9 @@ #include "src/core/lib/security/credentials/external/url_external_account_credentials.h" +#include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" +#include "absl/strings/str_split.h" namespace grpc_core { @@ -57,6 +59,10 @@ UrlExternalAccountCredentials::UrlExternalAccountCredentials( return; } url_ = *tmp_url; + // The url must follow the format of :/// + std::vector v = + absl::StrSplit(it->second.string_value(), absl::MaxSplits('/', 3)); + url_full_path_ = absl::StrCat("/", v[3]); it = options.credential_source.object_value().find("headers"); if (it != options.credential_source.object_value().end()) { if (it->second.type() != Json::Type::OBJECT) { @@ -121,7 +127,7 @@ void UrlExternalAccountCredentials::RetrieveSubjectToken( grpc_httpcli_request request; memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = const_cast(url_.authority().c_str()); - request.http.path = gpr_strdup(url_.path().c_str()); + request.http.path = gpr_strdup(url_full_path_.c_str()); grpc_http_header* headers = nullptr; request.http.hdr_count = headers_.size(); headers = static_cast( diff --git a/src/core/lib/security/credentials/external/url_external_account_credentials.h b/src/core/lib/security/credentials/external/url_external_account_credentials.h index 16f6f36c035..a324a07d8b2 100644 --- a/src/core/lib/security/credentials/external/url_external_account_credentials.h +++ b/src/core/lib/security/credentials/external/url_external_account_credentials.h @@ -45,6 +45,7 @@ class UrlExternalAccountCredentials final : public ExternalAccountCredentials { // Fields of credential source URI url_; + std::string url_full_path_; std::map headers_; std::string format_type_; std::string format_subject_token_field_name_; diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index dadc14caac6..859bbe5ba1d 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -156,6 +156,12 @@ static const char "{\"url\":\"https://foo.com:5555/generate_subject_token_format_text\"," "\"headers\":{\"Metadata-Flavor\":\"Google\"}}"; +static const char + valid_url_external_account_creds_options_credential_source_with_qurey_params_format_text + [] = "{\"url\":\"https://foo.com:5555/" + "path/to/url/creds?p1=v1&p2=v2\"," + "\"headers\":{\"Metadata-Flavor\":\"Google\"}}"; + static const char valid_url_external_account_creds_retrieve_subject_token_response_format_text [] = "test_subject_token"; @@ -2081,6 +2087,11 @@ static int url_external_account_creds_httpcli_get_success( *response = http_response( 200, valid_url_external_account_creds_retrieve_subject_token_response_format_text); + } else if (strcmp(request->http.path, "/path/to/url/creds?p1=v1&p2=v2") == + 0) { + *response = http_response( + 200, + valid_url_external_account_creds_retrieve_subject_token_response_format_text); } else if (strcmp(request->http.path, "/generate_subject_token_format_json") == 0) { *response = http_response( @@ -2384,6 +2395,44 @@ static void test_url_external_account_creds_success_format_text(void) { grpc_httpcli_set_override(nullptr, nullptr); } +static void +test_url_external_account_creds_success_with_qurey_params_format_text(void) { + expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}}; + grpc_core::ExecCtx exec_ctx; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, + nullptr, nullptr}; + grpc_error* error = GRPC_ERROR_NONE; + grpc_core::Json credential_source = grpc_core::Json::Parse( + valid_url_external_account_creds_options_credential_source_with_qurey_params_format_text, + &error); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_core::ExternalAccountCredentials::ExternalAccountCredentialsOptions + options = { + "external_account", // type; + "audience", // audience; + "subject_token_type", // subject_token_type; + "", // service_account_impersonation_url; + "https://foo.com:5555/token", // token_url; + "https://foo.com:5555/token_info", // token_info_url; + credential_source, // credential_source; + "quota_project_id", // quota_project_id; + "client_id", // client_id; + "client_secret", // client_secret; + }; + auto creds = + grpc_core::UrlExternalAccountCredentials::Create(options, {}, &error); + GPR_ASSERT(creds != nullptr); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); + request_metadata_state* state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(url_external_account_creds_httpcli_get_success, + external_account_creds_httpcli_post_success); + run_request_metadata_test(creds.get(), auth_md_ctx, state); + grpc_core::ExecCtx::Get()->Flush(); + grpc_httpcli_set_override(nullptr, nullptr); +} + static void test_url_external_account_creds_success_format_json(void) { expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}}; grpc_core::ExecCtx exec_ctx; @@ -3046,6 +3095,7 @@ int main(int argc, char** argv) { test_url_external_account_creds_success_format_text(); test_url_external_account_creds_success_format_json(); test_url_external_account_creds_failure_invalid_credential_source_url(); + test_url_external_account_creds_success_with_qurey_params_format_text(); test_file_external_account_creds_success_format_text(); test_file_external_account_creds_success_format_json(); test_file_external_account_creds_failure_file_not_found();