diff --git a/grpc.def b/grpc.def index ec4f21b6420..4dcb9edffb8 100644 --- a/grpc.def +++ b/grpc.def @@ -110,6 +110,7 @@ EXPORTS grpc_google_compute_engine_credentials_create grpc_max_auth_token_lifetime grpc_service_account_jwt_access_credentials_create + grpc_external_account_credentials_create grpc_google_refresh_token_credentials_create grpc_access_token_credentials_create grpc_google_iam_credentials_create diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 51339291754..c1d729559d3 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -330,6 +330,14 @@ grpc_service_account_jwt_access_credentials_create(const char* json_key, gpr_timespec token_lifetime, void* reserved); +/** Builds External Account credentials. + - json_string is the JSON string containing the credentials options. + - scopes_string contains the scopes to be binded with the credentials. + This API is used for experimental purposes for now and may change in the + future. */ +GRPCAPI grpc_call_credentials* grpc_external_account_credentials_create( + const char* json_string, const char* scopes_string); + /** Creates an Oauth2 Refresh Token credentials object for connecting to Google. May return NULL if the input is invalid. WARNING: Do NOT use this credentials to connect to a non-google service as diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index 2eae890fc70..98b5d9a42a1 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -307,6 +307,12 @@ grpc::Status StsCredentialsOptionsFromEnv(StsCredentialsOptions* options); std::shared_ptr StsCredentials( const StsCredentialsOptions& options); +/// Builds External Account credentials. +/// json_string is the JSON string containing the credentials options. +/// scopes contains the scopes to be binded with the credentials. +std::shared_ptr ExternalAccountCredentials( + const grpc::string& json_string, const std::vector& scopes); + std::shared_ptr MetadataCredentialsFromPlugin( std::unique_ptr plugin, grpc_security_level min_security_level); diff --git a/src/core/lib/security/credentials/external/aws_external_account_credentials.cc b/src/core/lib/security/credentials/external/aws_external_account_credentials.cc index 64effa938fa..e9d60ead2de 100644 --- a/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/aws_external_account_credentials.cc @@ -55,7 +55,7 @@ std::string UrlEncode(const absl::string_view& s) { } // namespace RefCountedPtr -AwsExternalAccountCredentials::Create(ExternalAccountCredentialsOptions options, +AwsExternalAccountCredentials::Create(Options options, std::vector scopes, grpc_error** error) { auto creds = MakeRefCounted( @@ -68,8 +68,7 @@ AwsExternalAccountCredentials::Create(ExternalAccountCredentialsOptions options, } AwsExternalAccountCredentials::AwsExternalAccountCredentials( - ExternalAccountCredentialsOptions options, std::vector scopes, - grpc_error** error) + Options options, std::vector scopes, grpc_error** error) : ExternalAccountCredentials(options, std::move(scopes)) { audience_ = options.audience; auto it = options.credential_source.object_value().find("environment_id"); @@ -121,7 +120,7 @@ AwsExternalAccountCredentials::AwsExternalAccountCredentials( } void AwsExternalAccountCredentials::RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) { if (ctx == nullptr) { FinishRetrieveSubjectToken( diff --git a/src/core/lib/security/credentials/external/aws_external_account_credentials.h b/src/core/lib/security/credentials/external/aws_external_account_credentials.h index 7e5bea2486f..edb7e825868 100644 --- a/src/core/lib/security/credentials/external/aws_external_account_credentials.h +++ b/src/core/lib/security/credentials/external/aws_external_account_credentials.h @@ -28,16 +28,15 @@ namespace grpc_core { class AwsExternalAccountCredentials final : public ExternalAccountCredentials { public: static RefCountedPtr Create( - ExternalAccountCredentialsOptions options, - std::vector scopes, grpc_error** error); + Options options, std::vector scopes, grpc_error** error); - AwsExternalAccountCredentials(ExternalAccountCredentialsOptions options, + AwsExternalAccountCredentials(Options options, std::vector scopes, grpc_error** error); private: void RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) override; void RetrieveRegion(); diff --git a/src/core/lib/security/credentials/external/external_account_credentials.cc b/src/core/lib/security/credentials/external/external_account_credentials.cc index 4327695d3df..127a5f39ed7 100644 --- a/src/core/lib/security/credentials/external/external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/external_account_credentials.cc @@ -19,6 +19,7 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" +#include "absl/strings/str_split.h" #include "absl/time/clock.h" #include "absl/time/time.h" @@ -26,6 +27,10 @@ #include "src/core/lib/security/util/json_util.h" #include "src/core/lib/slice/b64.h" +#include "src/core/lib/security/credentials/external/aws_external_account_credentials.h" +#include "src/core/lib/security/credentials/external/file_external_account_credentials.h" +#include "src/core/lib/security/credentials/external/url_external_account_credentials.h" + #define EXTERNAL_ACCOUNT_CREDENTIALS_GRANT_TYPE \ "urn:ietf:params:oauth:grant-type:token-exchange" #define EXTERNAL_ACCOUNT_CREDENTIALS_REQUESTED_TOKEN_TYPE \ @@ -57,8 +62,122 @@ std::string UrlEncode(const absl::string_view& s) { } // namespace +RefCountedPtr ExternalAccountCredentials::Create( + const Json& json, std::vector scopes, grpc_error** error) { + GPR_ASSERT(*error == GRPC_ERROR_NONE); + Options options; + options.type = GRPC_AUTH_JSON_TYPE_INVALID; + if (json.type() != Json::Type::OBJECT) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid json to construct credentials options."); + return nullptr; + } + auto it = json.object_value().find("type"); + if (it == json.object_value().end()) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("type field not present."); + return nullptr; + } + if (it->second.type() != Json::Type::STRING) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("type field must be a string."); + return nullptr; + } + if (it->second.string_value() != GRPC_AUTH_JSON_TYPE_EXTERNAL_ACCOUNT) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Invalid credentials json type."); + return nullptr; + } + options.type = GRPC_AUTH_JSON_TYPE_EXTERNAL_ACCOUNT; + it = json.object_value().find("audience"); + if (it == json.object_value().end()) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("audience field not present."); + return nullptr; + } + if (it->second.type() != Json::Type::STRING) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "audience field must be a string."); + return nullptr; + } + options.audience = it->second.string_value(); + it = json.object_value().find("subject_token_type"); + if (it == json.object_value().end()) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "subject_token_type field not present."); + return nullptr; + } + if (it->second.type() != Json::Type::STRING) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "subject_token_type field must be a string."); + return nullptr; + } + options.subject_token_type = it->second.string_value(); + it = json.object_value().find("service_account_impersonation_url"); + if (it != json.object_value().end()) { + options.service_account_impersonation_url = it->second.string_value(); + } + it = json.object_value().find("token_url"); + if (it == json.object_value().end()) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("token_url field not present."); + return nullptr; + } + if (it->second.type() != Json::Type::STRING) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "token_url field must be a string."); + return nullptr; + } + options.token_url = it->second.string_value(); + it = json.object_value().find("token_info_url"); + if (it != json.object_value().end()) { + options.token_info_url = it->second.string_value(); + } + it = json.object_value().find("credential_source"); + if (it == json.object_value().end()) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "credential_source field not present."); + return nullptr; + } + options.credential_source = it->second; + it = json.object_value().find("quota_project_id"); + if (it != json.object_value().end()) { + options.quota_project_id = it->second.string_value(); + } + it = json.object_value().find("client_id"); + if (it != json.object_value().end()) { + options.client_id = it->second.string_value(); + } + it = json.object_value().find("client_secret"); + if (it != json.object_value().end()) { + options.client_secret = it->second.string_value(); + } + RefCountedPtr creds; + if (options.credential_source.object_value().find("environment_id") != + options.credential_source.object_value().end()) { + creds = MakeRefCounted( + std::move(options), std::move(scopes), error); + } else if (options.credential_source.object_value().find("file") != + options.credential_source.object_value().end()) { + creds = MakeRefCounted( + std::move(options), std::move(scopes), error); + } else if (options.credential_source.object_value().find("url") != + options.credential_source.object_value().end()) { + creds = MakeRefCounted( + std::move(options), std::move(scopes), error); + } else { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid options credential source to create " + "ExternalAccountCredentials."); + } + if (*error == GRPC_ERROR_NONE) { + return creds; + } else { + return nullptr; + } +} + ExternalAccountCredentials::ExternalAccountCredentials( - ExternalAccountCredentialsOptions options, std::vector scopes) + Options options, std::vector scopes) : options_(std::move(options)) { if (scopes.empty()) { scopes.push_back(GOOGLE_CLOUD_PLATFORM_DEFAULT_SCOPE); @@ -351,3 +470,28 @@ void ExternalAccountCredentials::FinishTokenFetch(grpc_error* error) { } } // namespace grpc_core + +grpc_call_credentials* grpc_external_account_credentials_create( + const char* json_string, const char* scopes_string) { + grpc_error* error = GRPC_ERROR_NONE; + grpc_core::Json json = grpc_core::Json::Parse(json_string, &error); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, + "External account credentials creation failed. Error: %s.", + grpc_error_string(error)); + GRPC_ERROR_UNREF(error); + return nullptr; + } + std::vector scopes = absl::StrSplit(scopes_string, ','); + auto creds = grpc_core::ExternalAccountCredentials::Create( + json, std::move(scopes), &error) + .release(); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, + "External account credentials creation failed. Error: %s.", + grpc_error_string(error)); + GRPC_ERROR_UNREF(error); + return nullptr; + } + return creds; +} diff --git a/src/core/lib/security/credentials/external/external_account_credentials.h b/src/core/lib/security/credentials/external/external_account_credentials.h index 04f09d4a25d..0da778601ad 100644 --- a/src/core/lib/security/credentials/external/external_account_credentials.h +++ b/src/core/lib/security/credentials/external/external_account_credentials.h @@ -35,7 +35,7 @@ class ExternalAccountCredentials : public grpc_oauth2_token_fetcher_credentials { public: // External account credentials json interface. - struct ExternalAccountCredentialsOptions { + struct Options { std::string type; std::string audience; std::string subject_token_type; @@ -48,8 +48,10 @@ class ExternalAccountCredentials std::string client_secret; }; - ExternalAccountCredentials(ExternalAccountCredentialsOptions options, - std::vector scopes); + static RefCountedPtr Create( + const Json& json, std::vector scopes, grpc_error** error); + + ExternalAccountCredentials(Options options, std::vector scopes); ~ExternalAccountCredentials() override; std::string debug_string() override; @@ -81,7 +83,7 @@ class ExternalAccountCredentials // the callback function (cb) to pass the subject token (or error) // back. virtual void RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) = 0; private: @@ -105,7 +107,7 @@ class ExternalAccountCredentials void FinishTokenFetch(grpc_error* error); - ExternalAccountCredentialsOptions options_; + Options options_; std::vector scopes_; HTTPRequestContext* ctx_ = nullptr; diff --git a/src/core/lib/security/credentials/external/file_external_account_credentials.cc b/src/core/lib/security/credentials/external/file_external_account_credentials.cc index f2724f07751..730c0951999 100644 --- a/src/core/lib/security/credentials/external/file_external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/file_external_account_credentials.cc @@ -26,9 +26,9 @@ namespace grpc_core { RefCountedPtr -FileExternalAccountCredentials::Create( - ExternalAccountCredentialsOptions options, std::vector scopes, - grpc_error** error) { +FileExternalAccountCredentials::Create(Options options, + std::vector scopes, + grpc_error** error) { auto creds = MakeRefCounted( std::move(options), std::move(scopes), error); if (*error == GRPC_ERROR_NONE) { @@ -39,8 +39,7 @@ FileExternalAccountCredentials::Create( } FileExternalAccountCredentials::FileExternalAccountCredentials( - ExternalAccountCredentialsOptions options, std::vector scopes, - grpc_error** error) + Options options, std::vector scopes, grpc_error** error) : ExternalAccountCredentials(options, std::move(scopes)) { auto it = options.credential_source.object_value().find("file"); if (it == options.credential_source.object_value().end()) { @@ -92,7 +91,7 @@ FileExternalAccountCredentials::FileExternalAccountCredentials( } void FileExternalAccountCredentials::RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) { struct SliceWrapper { ~SliceWrapper() { grpc_slice_unref_internal(slice); } diff --git a/src/core/lib/security/credentials/external/file_external_account_credentials.h b/src/core/lib/security/credentials/external/file_external_account_credentials.h index 49b4d318895..7df5b6b8c2c 100644 --- a/src/core/lib/security/credentials/external/file_external_account_credentials.h +++ b/src/core/lib/security/credentials/external/file_external_account_credentials.h @@ -26,16 +26,15 @@ namespace grpc_core { class FileExternalAccountCredentials final : public ExternalAccountCredentials { public: static RefCountedPtr Create( - ExternalAccountCredentialsOptions options, - std::vector scopes, grpc_error** error); + Options options, std::vector scopes, grpc_error** error); - FileExternalAccountCredentials(ExternalAccountCredentialsOptions options, + FileExternalAccountCredentials(Options options, std::vector scopes, grpc_error** error); private: void RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) override; // Fields of credential source 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 76f50db53dc..85d09be933d 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 @@ -24,7 +24,7 @@ namespace grpc_core { RefCountedPtr -UrlExternalAccountCredentials::Create(ExternalAccountCredentialsOptions options, +UrlExternalAccountCredentials::Create(Options options, std::vector scopes, grpc_error** error) { auto creds = MakeRefCounted( @@ -37,8 +37,7 @@ UrlExternalAccountCredentials::Create(ExternalAccountCredentialsOptions options, } UrlExternalAccountCredentials::UrlExternalAccountCredentials( - ExternalAccountCredentialsOptions options, std::vector scopes, - grpc_error** error) + Options options, std::vector scopes, grpc_error** error) : ExternalAccountCredentials(options, std::move(scopes)) { auto it = options.credential_source.object_value().find("url"); if (it == options.credential_source.object_value().end()) { @@ -113,7 +112,7 @@ UrlExternalAccountCredentials::UrlExternalAccountCredentials( } void UrlExternalAccountCredentials::RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) { if (ctx == nullptr) { FinishRetrieveSubjectToken( 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 a324a07d8b2..4e37c5735fb 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 @@ -26,16 +26,15 @@ namespace grpc_core { class UrlExternalAccountCredentials final : public ExternalAccountCredentials { public: static RefCountedPtr Create( - ExternalAccountCredentialsOptions options, - std::vector scopes, grpc_error** error); + Options options, std::vector scopes, grpc_error** error); - UrlExternalAccountCredentials(ExternalAccountCredentialsOptions options, + UrlExternalAccountCredentials(Options options, std::vector scopes, grpc_error** error); private: void RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) override; static void OnRetrieveSubjectToken(void* arg, grpc_error* error); diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc index 4ff87c9b7dd..d1de87db04d 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -38,6 +38,7 @@ #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/security/credentials/alts/alts_credentials.h" #include "src/core/lib/security/credentials/alts/check_gcp_environment.h" +#include "src/core/lib/security/credentials/external/external_account_credentials.h" #include "src/core/lib/security/credentials/google_default/google_default_credentials.h" #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" @@ -269,6 +270,9 @@ static grpc_error* create_default_creds_from_path( goto end; } + /* Finally try an external account credentials.*/ + result = grpc_core::ExternalAccountCredentials::Create(json, {}, &error); + end: GPR_ASSERT((result == nullptr) + (error == GRPC_ERROR_NONE) == 1); grpc_slice_unref_internal(creds_data); diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index af2841c8f43..4facd2b821b 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -28,6 +28,8 @@ #include #include +#include "absl/strings/str_join.h" + // TODO(yashykt): We shouldn't be including "src/core" headers. #include "src/core/lib/gpr/env.h" #include "src/core/lib/iomgr/error.h" @@ -107,6 +109,17 @@ std::shared_ptr GoogleDefaultCredentials() { grpc_google_default_credentials_create(nullptr)); } +namespace experimental { + +std::shared_ptr ExternalAccountCredentials( + const grpc::string& json_string, const std::vector& scopes) { + grpc::GrpcLibraryCodegen init; // To call grpc_init(). + return WrapCallCredentials(grpc_external_account_credentials_create( + json_string.c_str(), absl::StrJoin(scopes, ",").c_str())); +} + +} // namespace experimental + // Builds SSL Credentials given SSL specific options std::shared_ptr SslCredentials( const SslCredentialsOptions& options) { diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index edc7203633e..5d5d3e01d8a 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -133,6 +133,7 @@ grpc_composite_call_credentials_create_type grpc_composite_call_credentials_crea grpc_google_compute_engine_credentials_create_type grpc_google_compute_engine_credentials_create_import; grpc_max_auth_token_lifetime_type grpc_max_auth_token_lifetime_import; grpc_service_account_jwt_access_credentials_create_type grpc_service_account_jwt_access_credentials_create_import; +grpc_external_account_credentials_create_type grpc_external_account_credentials_create_import; grpc_google_refresh_token_credentials_create_type grpc_google_refresh_token_credentials_create_import; grpc_access_token_credentials_create_type grpc_access_token_credentials_create_import; grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_import; @@ -416,6 +417,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_google_compute_engine_credentials_create_import = (grpc_google_compute_engine_credentials_create_type) GetProcAddress(library, "grpc_google_compute_engine_credentials_create"); grpc_max_auth_token_lifetime_import = (grpc_max_auth_token_lifetime_type) GetProcAddress(library, "grpc_max_auth_token_lifetime"); grpc_service_account_jwt_access_credentials_create_import = (grpc_service_account_jwt_access_credentials_create_type) GetProcAddress(library, "grpc_service_account_jwt_access_credentials_create"); + grpc_external_account_credentials_create_import = (grpc_external_account_credentials_create_type) GetProcAddress(library, "grpc_external_account_credentials_create"); grpc_google_refresh_token_credentials_create_import = (grpc_google_refresh_token_credentials_create_type) GetProcAddress(library, "grpc_google_refresh_token_credentials_create"); grpc_access_token_credentials_create_import = (grpc_access_token_credentials_create_type) GetProcAddress(library, "grpc_access_token_credentials_create"); grpc_google_iam_credentials_create_import = (grpc_google_iam_credentials_create_type) GetProcAddress(library, "grpc_google_iam_credentials_create"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 8adea95481e..c526b3a7c03 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -374,6 +374,9 @@ extern grpc_max_auth_token_lifetime_type 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); 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); +extern grpc_external_account_credentials_create_type grpc_external_account_credentials_create_import; +#define grpc_external_account_credentials_create grpc_external_account_credentials_create_import typedef grpc_call_credentials*(*grpc_google_refresh_token_credentials_create_type)(const char* json_refresh_token, void* reserved); extern grpc_google_refresh_token_credentials_create_type grpc_google_refresh_token_credentials_create_import; #define grpc_google_refresh_token_credentials_create grpc_google_refresh_token_credentials_create_import diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index 91d8494140e..6106f6d4384 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -2206,13 +2206,13 @@ static int aws_external_account_creds_httpcli_post_success( class TestExternalAccountCredentials final : public grpc_core::ExternalAccountCredentials { public: - TestExternalAccountCredentials(ExternalAccountCredentialsOptions options, + TestExternalAccountCredentials(Options options, std::vector scopes) : ExternalAccountCredentials(std::move(options), std::move(scopes)) {} protected: void RetrieveSubjectToken( - HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options, + HTTPRequestContext* ctx, const Options& options, std::function cb) override { cb("test_subject_token", GRPC_ERROR_NONE); } @@ -2224,7 +2224,7 @@ static void test_external_account_creds_success(void) { grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; grpc_core::Json credential_source(""); - TestExternalAccountCredentials::ExternalAccountCredentialsOptions options = { + TestExternalAccountCredentials::Options options = { "external_account", // type; "audience", // audience; "subject_token_type", // subject_token_type; @@ -2262,7 +2262,7 @@ static void test_external_account_creds_success_with_url_encode(void) { grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; grpc_core::Json credential_source(""); - TestExternalAccountCredentials::ExternalAccountCredentialsOptions options = { + TestExternalAccountCredentials::Options options = { "external_account", // type; "audience_!@#$", // audience; "subject_token_type_!@#$", // subject_token_type; @@ -2292,7 +2292,7 @@ test_external_account_creds_success_with_service_account_impersonation(void) { grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; grpc_core::Json credential_source(""); - TestExternalAccountCredentials::ExternalAccountCredentialsOptions options = { + TestExternalAccountCredentials::Options options = { "external_account", // type; "audience", // audience; "subject_token_type", // subject_token_type; @@ -2322,7 +2322,7 @@ static void test_external_account_creds_failure_invalid_token_url(void) { grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; grpc_core::Json credential_source(""); - TestExternalAccountCredentials::ExternalAccountCredentialsOptions options = { + TestExternalAccountCredentials::Options options = { "external_account", // type; "audience", // audience; "subject_token_type", // subject_token_type; @@ -2356,7 +2356,7 @@ test_external_account_creds_failure_invalid_service_account_impersonation_url( grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; grpc_core::Json credential_source(""); - TestExternalAccountCredentials::ExternalAccountCredentialsOptions options = { + TestExternalAccountCredentials::Options options = { "external_account", // type; "audience", // audience; "subject_token_type", // subject_token_type; @@ -2391,7 +2391,7 @@ test_external_account_creds_failure_token_exchange_response_missing_access_token grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; grpc_core::Json credential_source(""); - TestExternalAccountCredentials::ExternalAccountCredentialsOptions options = { + TestExternalAccountCredentials::Options options = { "external_account", // type; "audience", // audience; "subject_token_type", // subject_token_type; @@ -2431,19 +2431,18 @@ static void test_url_external_account_creds_success_format_text(void) { valid_url_external_account_creds_options_credential_source_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; - }; + grpc_core::ExternalAccountCredentials::Options 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); @@ -2469,19 +2468,18 @@ test_url_external_account_creds_success_with_qurey_params_format_text(void) { 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; - }; + grpc_core::ExternalAccountCredentials::Options 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); @@ -2506,19 +2504,18 @@ static void test_url_external_account_creds_success_format_json(void) { valid_url_external_account_creds_options_credential_source_format_json, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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); @@ -2539,19 +2536,18 @@ test_url_external_account_creds_failure_invalid_credential_source_url(void) { grpc_core::Json credential_source = grpc_core::Json::Parse( invalid_url_external_account_creds_options_credential_source, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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); @@ -2577,19 +2573,18 @@ static void test_file_external_account_creds_success_format_text(void) { absl::StrReplaceAll(subject_token_path, {{"\\", "\\\\"}})), &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::FileExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2627,19 +2622,18 @@ static void test_file_external_account_creds_success_format_json(void) { absl::StrReplaceAll(subject_token_path, {{"\\", "\\\\"}})), &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::FileExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2664,19 +2658,18 @@ static void test_file_external_account_creds_failure_file_not_found(void) { grpc_core::Json credential_source = grpc_core::Json::Parse("{\"file\":\"non_exisiting_file\"}", &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::FileExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2714,19 +2707,18 @@ static void test_file_external_account_creds_failure_invalid_json_content( absl::StrReplaceAll(subject_token_path, {{"\\", "\\\\"}})), &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::FileExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2755,19 +2747,18 @@ static void test_aws_external_account_creds_success(void) { grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2793,19 +2784,18 @@ static void test_aws_external_account_creds_success_path_region_env_keys_url( grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2834,19 +2824,18 @@ static void test_aws_external_account_creds_success_path_region_url_keys_env( grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2878,19 +2867,18 @@ static void test_aws_external_account_creds_success_path_region_env_keys_env( grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2916,19 +2904,18 @@ static void test_aws_external_account_creds_failure_unmatched_environment_id( invalid_aws_external_account_creds_options_credential_source_unmatched_environment_id, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds == nullptr); @@ -2950,19 +2937,18 @@ static void test_aws_external_account_creds_failure_invalid_region_url(void) { invalid_aws_external_account_creds_options_credential_source_invalid_region_url, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -2991,19 +2977,18 @@ static void test_aws_external_account_creds_failure_invalid_url(void) { invalid_aws_external_account_creds_options_credential_source_invalid_url, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -3031,19 +3016,18 @@ static void test_aws_external_account_creds_failure_missing_role_name(void) { invalid_aws_external_account_creds_options_credential_source_missing_role_name, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -3074,19 +3058,18 @@ test_aws_external_account_creds_failure_invalid_regional_cred_verification_url( invalid_aws_external_account_creds_options_credential_source_invalid_regional_cred_verification_url, &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; - }; + grpc_core::ExternalAccountCredentials::Options 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::AwsExternalAccountCredentials::Create(options, {}, &error); GPR_ASSERT(creds != nullptr); @@ -3106,6 +3089,92 @@ test_aws_external_account_creds_failure_invalid_regional_cred_verification_url( GRPC_ERROR_UNREF(error); } +static void test_external_account_credentials_create_success(void) { + // url credentials + const char* url_options_string = + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/" + "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":" + "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":" + "\"access_token\"}},\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"; + const char* url_scopes_string = "scope1,scope2"; + grpc_call_credentials* url_creds = grpc_external_account_credentials_create( + url_options_string, url_scopes_string); + GPR_ASSERT(url_creds != nullptr); + url_creds->Unref(); + // file credentials + const char* file_options_string = + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"file\":\"credentials_file_path\"}," + "\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"; + const char* file_scopes_string = "scope1,scope2"; + grpc_call_credentials* file_creds = grpc_external_account_credentials_create( + file_options_string, file_scopes_string); + GPR_ASSERT(file_creds != nullptr); + file_creds->Unref(); + // aws credentials + const char* aws_options_string = + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"environment_id\":\"aws1\"," + "\"region_url\":\"https://foo.com:5555/region_url\",\"url\":\"https://" + "foo.com:5555/url\",\"regional_cred_verification_url\":\"https://" + "foo.com:5555/regional_cred_verification_url_{region}\"}," + "\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"; + const char* aws_scopes_string = "scope1,scope2"; + grpc_call_credentials* aws_creds = grpc_external_account_credentials_create( + aws_options_string, aws_scopes_string); + GPR_ASSERT(aws_creds != nullptr); + aws_creds->Unref(); +} + +static void +test_external_account_credentials_create_failure_invalid_json_format(void) { + const char* options_string = "invalid_json"; + grpc_call_credentials* creds = + grpc_external_account_credentials_create(options_string, ""); + GPR_ASSERT(creds == nullptr); +} + +static void +test_external_account_credentials_create_failure_invalid_options_format(void) { + const char* options_string = "{\"random_key\":\"random_value\"}"; + grpc_call_credentials* creds = + grpc_external_account_credentials_create(options_string, ""); + GPR_ASSERT(creds == nullptr); +} + +static void +test_external_account_credentials_create_failure_invalid_options_credential_source( + void) { + const char* options_string = + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"random_key\":\"random_value\"}," + "\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"; + grpc_call_credentials* creds = + grpc_external_account_credentials_create(options_string, ""); + GPR_ASSERT(creds == nullptr); +} + int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); grpc_init(); @@ -3173,6 +3242,10 @@ int main(int argc, char** argv) { test_aws_external_account_creds_failure_invalid_url(); test_aws_external_account_creds_failure_missing_role_name(); test_aws_external_account_creds_failure_invalid_regional_cred_verification_url(); + test_external_account_credentials_create_success(); + test_external_account_credentials_create_failure_invalid_json_format(); + test_external_account_credentials_create_failure_invalid_options_format(); + test_external_account_credentials_create_failure_invalid_options_credential_source(); grpc_shutdown(); return 0; } diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 8424b1da2d8..22f89ba27a4 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -177,6 +177,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_google_compute_engine_credentials_create); printf("%lx", (unsigned long) grpc_max_auth_token_lifetime); printf("%lx", (unsigned long) grpc_service_account_jwt_access_credentials_create); + printf("%lx", (unsigned long) grpc_external_account_credentials_create); printf("%lx", (unsigned long) grpc_google_refresh_token_credentials_create); printf("%lx", (unsigned long) grpc_access_token_credentials_create); printf("%lx", (unsigned long) grpc_google_iam_credentials_create); diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index b2ec888ae53..ddfb3df3d16 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -97,6 +97,53 @@ TEST(CredentialsTest, DefaultCredentials) { auto creds = GoogleDefaultCredentials(); } +TEST(CredentialsTest, ExternalAccountCredentials) { + // url credentials + std::string url_options_string( + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/" + "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":" + "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":" + "\"access_token\"}},\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"); + auto url_creds = grpc::experimental::ExternalAccountCredentials( + url_options_string, {"scope1", "scope2"}); + EXPECT_TRUE(url_creds != nullptr); + // file credentials + std::string file_options_string( + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"file\":\"credentials_file_path\"}," + "\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"); + auto file_creds = grpc::experimental::ExternalAccountCredentials( + file_options_string, {"scope1", "scope2"}); + EXPECT_TRUE(file_creds != nullptr); + // aws credentials + std::string aws_options_string( + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"environment_id\":\"aws1\"," + "\"region_url\":\"https://foo.com:5555/region_url\",\"url\":\"https://" + "foo.com:5555/url\",\"regional_cred_verification_url\":\"https://" + "foo.com:5555/regional_cred_verification_url_{region}\"}," + "\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"); + auto aws_creds = grpc::experimental::ExternalAccountCredentials( + aws_options_string, {"scope1", "scope2"}); + EXPECT_TRUE(aws_creds != nullptr); +} + TEST(CredentialsTest, StsCredentialsOptionsCppToCore) { grpc::experimental::StsCredentialsOptions options; options.token_exchange_service_uri = "https://foo.com/exchange";