diff --git a/BUILD b/BUILD
index 57f7abe8458..d07546280d3 100644
--- a/BUILD
+++ b/BUILD
@@ -1794,6 +1794,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/credentials.cc",
"src/core/lib/security/credentials/credentials_metadata.cc",
"src/core/lib/security/credentials/external/external_account_credentials.cc",
+ "src/core/lib/security/credentials/external/file_external_account_credentials.cc",
"src/core/lib/security/credentials/external/url_external_account_credentials.cc",
"src/core/lib/security/credentials/fake/fake_credentials.cc",
"src/core/lib/security/credentials/google_default/credentials_generic.cc",
@@ -1838,6 +1839,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/composite/composite_credentials.h",
"src/core/lib/security/credentials/credentials.h",
"src/core/lib/security/credentials/external/external_account_credentials.h",
+ "src/core/lib/security/credentials/external/file_external_account_credentials.h",
"src/core/lib/security/credentials/external/url_external_account_credentials.h",
"src/core/lib/security/credentials/fake/fake_credentials.h",
"src/core/lib/security/credentials/google_default/google_default_credentials.h",
diff --git a/BUILD.gn b/BUILD.gn
index 9de54fe9a7a..0c0f30d5654 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1002,6 +1002,8 @@ config("grpc_config") {
"src/core/lib/security/credentials/credentials_metadata.cc",
"src/core/lib/security/credentials/external/external_account_credentials.cc",
"src/core/lib/security/credentials/external/external_account_credentials.h",
+ "src/core/lib/security/credentials/external/file_external_account_credentials.cc",
+ "src/core/lib/security/credentials/external/file_external_account_credentials.h",
"src/core/lib/security/credentials/external/url_external_account_credentials.cc",
"src/core/lib/security/credentials/external/url_external_account_credentials.h",
"src/core/lib/security/credentials/fake/fake_credentials.cc",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9a25f4552b0..c8f1e9e2f82 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1846,6 +1846,7 @@ add_library(grpc
src/core/lib/security/credentials/credentials.cc
src/core/lib/security/credentials/credentials_metadata.cc
src/core/lib/security/credentials/external/external_account_credentials.cc
+ src/core/lib/security/credentials/external/file_external_account_credentials.cc
src/core/lib/security/credentials/external/url_external_account_credentials.cc
src/core/lib/security/credentials/fake/fake_credentials.cc
src/core/lib/security/credentials/google_default/credentials_generic.cc
diff --git a/Makefile b/Makefile
index a63a1891989..94f8cc39489 100644
--- a/Makefile
+++ b/Makefile
@@ -2254,6 +2254,7 @@ LIBGRPC_SRC = \
src/core/lib/security/credentials/credentials.cc \
src/core/lib/security/credentials/credentials_metadata.cc \
src/core/lib/security/credentials/external/external_account_credentials.cc \
+ src/core/lib/security/credentials/external/file_external_account_credentials.cc \
src/core/lib/security/credentials/external/url_external_account_credentials.cc \
src/core/lib/security/credentials/fake/fake_credentials.cc \
src/core/lib/security/credentials/google_default/credentials_generic.cc \
@@ -4795,6 +4796,7 @@ src/core/lib/security/credentials/composite/composite_credentials.cc: $(OPENSSL_
src/core/lib/security/credentials/credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/credentials_metadata.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/external/external_account_credentials.cc: $(OPENSSL_DEP)
+src/core/lib/security/credentials/external/file_external_account_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/external/url_external_account_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/fake/fake_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/google_default/credentials_generic.cc: $(OPENSSL_DEP)
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index eb99f9a9cba..f73e9b9cb4a 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -760,6 +760,7 @@ libs:
- src/core/lib/security/credentials/composite/composite_credentials.h
- src/core/lib/security/credentials/credentials.h
- src/core/lib/security/credentials/external/external_account_credentials.h
+ - src/core/lib/security/credentials/external/file_external_account_credentials.h
- src/core/lib/security/credentials/external/url_external_account_credentials.h
- src/core/lib/security/credentials/fake/fake_credentials.h
- src/core/lib/security/credentials/google_default/google_default_credentials.h
@@ -1272,6 +1273,7 @@ libs:
- src/core/lib/security/credentials/credentials.cc
- src/core/lib/security/credentials/credentials_metadata.cc
- src/core/lib/security/credentials/external/external_account_credentials.cc
+ - src/core/lib/security/credentials/external/file_external_account_credentials.cc
- src/core/lib/security/credentials/external/url_external_account_credentials.cc
- src/core/lib/security/credentials/fake/fake_credentials.cc
- src/core/lib/security/credentials/google_default/credentials_generic.cc
diff --git a/config.m4 b/config.m4
index 42bf1f5d476..97800cc15e9 100644
--- a/config.m4
+++ b/config.m4
@@ -501,6 +501,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/credentials/credentials.cc \
src/core/lib/security/credentials/credentials_metadata.cc \
src/core/lib/security/credentials/external/external_account_credentials.cc \
+ src/core/lib/security/credentials/external/file_external_account_credentials.cc \
src/core/lib/security/credentials/external/url_external_account_credentials.cc \
src/core/lib/security/credentials/fake/fake_credentials.cc \
src/core/lib/security/credentials/google_default/credentials_generic.cc \
diff --git a/config.w32 b/config.w32
index 9485624f91b..8f2e6bc7827 100644
--- a/config.w32
+++ b/config.w32
@@ -468,6 +468,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\security\\credentials\\credentials.cc " +
"src\\core\\lib\\security\\credentials\\credentials_metadata.cc " +
"src\\core\\lib\\security\\credentials\\external\\external_account_credentials.cc " +
+ "src\\core\\lib\\security\\credentials\\external\\file_external_account_credentials.cc " +
"src\\core\\lib\\security\\credentials\\external\\url_external_account_credentials.cc " +
"src\\core\\lib\\security\\credentials\\fake\\fake_credentials.cc " +
"src\\core\\lib\\security\\credentials\\google_default\\credentials_generic.cc " +
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index d5af45ef9e0..f832e89f829 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -607,6 +607,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
'src/core/lib/security/credentials/external/external_account_credentials.h',
+ 'src/core/lib/security/credentials/external/file_external_account_credentials.h',
'src/core/lib/security/credentials/external/url_external_account_credentials.h',
'src/core/lib/security/credentials/fake/fake_credentials.h',
'src/core/lib/security/credentials/google_default/google_default_credentials.h',
@@ -1209,6 +1210,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
'src/core/lib/security/credentials/external/external_account_credentials.h',
+ 'src/core/lib/security/credentials/external/file_external_account_credentials.h',
'src/core/lib/security/credentials/external/url_external_account_credentials.h',
'src/core/lib/security/credentials/fake/fake_credentials.h',
'src/core/lib/security/credentials/google_default/google_default_credentials.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 2175c6066ba..1a84b55e45d 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -1059,6 +1059,8 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/credentials_metadata.cc',
'src/core/lib/security/credentials/external/external_account_credentials.cc',
'src/core/lib/security/credentials/external/external_account_credentials.h',
+ 'src/core/lib/security/credentials/external/file_external_account_credentials.cc',
+ 'src/core/lib/security/credentials/external/file_external_account_credentials.h',
'src/core/lib/security/credentials/external/url_external_account_credentials.cc',
'src/core/lib/security/credentials/external/url_external_account_credentials.h',
'src/core/lib/security/credentials/fake/fake_credentials.cc',
@@ -1736,6 +1738,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
'src/core/lib/security/credentials/external/external_account_credentials.h',
+ 'src/core/lib/security/credentials/external/file_external_account_credentials.h',
'src/core/lib/security/credentials/external/url_external_account_credentials.h',
'src/core/lib/security/credentials/fake/fake_credentials.h',
'src/core/lib/security/credentials/google_default/google_default_credentials.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 9d39899c137..d4ade6aa93d 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -976,6 +976,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/credentials_metadata.cc )
s.files += %w( src/core/lib/security/credentials/external/external_account_credentials.cc )
s.files += %w( src/core/lib/security/credentials/external/external_account_credentials.h )
+ s.files += %w( src/core/lib/security/credentials/external/file_external_account_credentials.cc )
+ s.files += %w( src/core/lib/security/credentials/external/file_external_account_credentials.h )
s.files += %w( src/core/lib/security/credentials/external/url_external_account_credentials.cc )
s.files += %w( src/core/lib/security/credentials/external/url_external_account_credentials.h )
s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.cc )
diff --git a/grpc.gyp b/grpc.gyp
index 8699f0fb5b4..db3c7e9686a 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -866,6 +866,7 @@
'src/core/lib/security/credentials/credentials.cc',
'src/core/lib/security/credentials/credentials_metadata.cc',
'src/core/lib/security/credentials/external/external_account_credentials.cc',
+ 'src/core/lib/security/credentials/external/file_external_account_credentials.cc',
'src/core/lib/security/credentials/external/url_external_account_credentials.cc',
'src/core/lib/security/credentials/fake/fake_credentials.cc',
'src/core/lib/security/credentials/google_default/credentials_generic.cc',
diff --git a/package.xml b/package.xml
index 6a2a5df29c2..25fa57adc08 100644
--- a/package.xml
+++ b/package.xml
@@ -956,6 +956,8 @@
+
+
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
new file mode 100644
index 00000000000..f2724f07751
--- /dev/null
+++ b/src/core/lib/security/credentials/external/file_external_account_credentials.cc
@@ -0,0 +1,136 @@
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include
+
+#include "src/core/lib/security/credentials/external/file_external_account_credentials.h"
+
+#include
+
+#include "src/core/lib/iomgr/load_file.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_utils.h"
+
+namespace grpc_core {
+
+RefCountedPtr
+FileExternalAccountCredentials::Create(
+ ExternalAccountCredentialsOptions options, std::vector scopes,
+ grpc_error** error) {
+ auto creds = MakeRefCounted(
+ std::move(options), std::move(scopes), error);
+ if (*error == GRPC_ERROR_NONE) {
+ return creds;
+ } else {
+ return nullptr;
+ }
+}
+
+FileExternalAccountCredentials::FileExternalAccountCredentials(
+ ExternalAccountCredentialsOptions 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()) {
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("file field not present.");
+ return;
+ }
+ if (it->second.type() != Json::Type::STRING) {
+ *error =
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("file field must be a string.");
+ return;
+ }
+ file_ = it->second.string_value();
+ it = options.credential_source.object_value().find("format");
+ if (it != options.credential_source.object_value().end()) {
+ const Json& format_json = it->second;
+ if (format_json.type() != Json::Type::OBJECT) {
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "The JSON value of credential source format is not an object.");
+ return;
+ }
+ auto format_it = format_json.object_value().find("type");
+ if (format_it == format_json.object_value().end()) {
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "format.type field not present.");
+ return;
+ }
+ if (format_it->second.type() != Json::Type::STRING) {
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "format.type field must be a string.");
+ return;
+ }
+ format_type_ = format_it->second.string_value();
+ if (format_type_ == "json") {
+ format_it = format_json.object_value().find("subject_token_field_name");
+ if (format_it == format_json.object_value().end()) {
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "format.subject_token_field_name field must be present if the "
+ "format is in Json.");
+ return;
+ }
+ if (format_it->second.type() != Json::Type::STRING) {
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "format.subject_token_field_name field must be a string.");
+ return;
+ }
+ format_subject_token_field_name_ = format_it->second.string_value();
+ }
+ }
+}
+
+void FileExternalAccountCredentials::RetrieveSubjectToken(
+ HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options,
+ std::function cb) {
+ struct SliceWrapper {
+ ~SliceWrapper() { grpc_slice_unref_internal(slice); }
+ grpc_slice slice = grpc_empty_slice();
+ };
+ SliceWrapper content_slice;
+ // To retrieve the subject token, we read the file every time we make a
+ // request because it may have changed since the last request.
+ grpc_error* error = grpc_load_file(file_.c_str(), 0, &content_slice.slice);
+ if (error != GRPC_ERROR_NONE) {
+ cb("", error);
+ return;
+ }
+ absl::string_view content = StringViewFromSlice(content_slice.slice);
+ if (format_type_ == "json") {
+ Json content_json = Json::Parse(content, &error);
+ if (error != GRPC_ERROR_NONE || content_json.type() != Json::Type::OBJECT) {
+ cb("", GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "The content of the file is not a valid json object."));
+ GRPC_ERROR_UNREF(error);
+ return;
+ }
+ auto content_it =
+ content_json.object_value().find(format_subject_token_field_name_);
+ if (content_it == content_json.object_value().end()) {
+ cb("", GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Subject token field not present."));
+ return;
+ }
+ if (content_it->second.type() != Json::Type::STRING) {
+ cb("", GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Subject token field must be a string."));
+ return;
+ }
+ cb(content_it->second.string_value(), GRPC_ERROR_NONE);
+ return;
+ }
+ cb(std::string(content), GRPC_ERROR_NONE);
+}
+
+} // namespace grpc_core
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
new file mode 100644
index 00000000000..49b4d318895
--- /dev/null
+++ b/src/core/lib/security/credentials/external/file_external_account_credentials.h
@@ -0,0 +1,49 @@
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_EXTERNAL_FILE_EXTERNAL_ACCOUNT_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_EXTERNAL_FILE_EXTERNAL_ACCOUNT_CREDENTIALS_H
+
+#include
+
+#include "src/core/lib/security/credentials/external/external_account_credentials.h"
+
+namespace grpc_core {
+
+class FileExternalAccountCredentials final : public ExternalAccountCredentials {
+ public:
+ static RefCountedPtr Create(
+ ExternalAccountCredentialsOptions options,
+ std::vector scopes, grpc_error** error);
+
+ FileExternalAccountCredentials(ExternalAccountCredentialsOptions options,
+ std::vector scopes,
+ grpc_error** error);
+
+ private:
+ void RetrieveSubjectToken(
+ HTTPRequestContext* ctx, const ExternalAccountCredentialsOptions& options,
+ std::function cb) override;
+
+ // Fields of credential source
+ std::string file_;
+ std::string format_type_;
+ std::string format_subject_token_field_name_;
+};
+
+} // namespace grpc_core
+
+#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_EXTERNAL_FILE_EXTERNAL_ACCOUNT_CREDENTIALS_H
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 0fc2e5ffb30..0881c4b42ea 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -477,6 +477,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/security/credentials/credentials.cc',
'src/core/lib/security/credentials/credentials_metadata.cc',
'src/core/lib/security/credentials/external/external_account_credentials.cc',
+ 'src/core/lib/security/credentials/external/file_external_account_credentials.cc',
'src/core/lib/security/credentials/external/url_external_account_credentials.cc',
'src/core/lib/security/credentials/fake/fake_credentials.cc',
'src/core/lib/security/credentials/google_default/credentials_generic.cc',
diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc
index ef6e326fc17..bd3b964586f 100644
--- a/test/core/security/credentials_test.cc
+++ b/test/core/security/credentials_test.cc
@@ -28,6 +28,7 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
#include
#include
@@ -44,6 +45,7 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/security/credentials/composite/composite_credentials.h"
#include "src/core/lib/security/credentials/external/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"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
@@ -2122,7 +2124,7 @@ test_external_account_creds_success_with_service_account_impersonation(void) {
grpc_httpcli_set_override(nullptr, nullptr);
}
-static void test_external_account_creds_faiure_invalid_token_url(void) {
+static void test_external_account_creds_failure_invalid_token_url(void) {
grpc_core::ExecCtx exec_ctx;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
@@ -2155,7 +2157,7 @@ static void test_external_account_creds_faiure_invalid_token_url(void) {
}
static void
-test_external_account_creds_faiure_invalid_service_account_impersonation_url(
+test_external_account_creds_failure_invalid_service_account_impersonation_url(
void) {
grpc_core::ExecCtx exec_ctx;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
@@ -2190,7 +2192,7 @@ test_external_account_creds_faiure_invalid_service_account_impersonation_url(
}
static void
-test_external_account_creds_faiure_token_exchange_response_missing_access_token(
+test_external_account_creds_failure_token_exchange_response_missing_access_token(
void) {
grpc_core::ExecCtx exec_ctx;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
@@ -2301,7 +2303,7 @@ static void test_url_external_account_creds_success_format_json(void) {
}
static void
-test_url_external_account_creds_faiure_invalid_credential_source_url(void) {
+test_url_external_account_creds_failure_invalid_credential_source_url(void) {
grpc_error* error = GRPC_ERROR_NONE;
grpc_core::Json credential_source = grpc_core::Json::Parse(
invalid_url_external_account_creds_options_credential_source, &error);
@@ -2331,6 +2333,188 @@ test_url_external_account_creds_faiure_invalid_credential_source_url(void) {
GRPC_ERROR_UNREF(error);
}
+static void test_file_external_account_creds_success_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;
+ char* subject_token_path = write_tmp_jwt_file("test_subject_token");
+ grpc_core::Json credential_source = grpc_core::Json::Parse(
+ absl::StrFormat(
+ "{\"file\":\"%s\"}",
+ 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;
+ };
+ auto creds =
+ grpc_core::FileExternalAccountCredentials::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(httpcli_get_should_not_be_called,
+ 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);
+ GRPC_ERROR_UNREF(error);
+ gpr_free(subject_token_path);
+}
+
+static void test_file_external_account_creds_success_format_json(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;
+ char* subject_token_path =
+ write_tmp_jwt_file("{\"access_token\":\"test_subject_token\"}");
+ grpc_core::Json credential_source = grpc_core::Json::Parse(
+ absl::StrFormat(
+ "{\n"
+ "\"file\":\"%s\",\n"
+ "\"format\":\n"
+ "{\n"
+ "\"type\":\"json\",\n"
+ "\"subject_token_field_name\":\"access_token\"\n"
+ "}\n"
+ "}",
+ 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;
+ };
+ auto creds =
+ grpc_core::FileExternalAccountCredentials::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(httpcli_get_should_not_be_called,
+ 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);
+ GRPC_ERROR_UNREF(error);
+ gpr_free(subject_token_path);
+}
+
+static void test_file_external_account_creds_failure_file_not_found(void) {
+ 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("{\"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;
+ };
+ auto creds =
+ grpc_core::FileExternalAccountCredentials::Create(options, {}, &error);
+ GPR_ASSERT(creds != nullptr);
+ GPR_ASSERT(error == GRPC_ERROR_NONE);
+ grpc_httpcli_set_override(httpcli_get_should_not_be_called,
+ httpcli_post_should_not_be_called);
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to load file");
+ grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ "Error occurred when fetching oauth2 token.", &error, 1);
+ request_metadata_state* state =
+ make_request_metadata_state(expected_error, nullptr, 0);
+ run_request_metadata_test(creds.get(), auth_md_ctx, state);
+ grpc_core::ExecCtx::Get()->Flush();
+ grpc_httpcli_set_override(nullptr, nullptr);
+ GRPC_ERROR_UNREF(error);
+}
+
+static void test_file_external_account_creds_failure_invalid_json_content(
+ void) {
+ 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;
+ char* subject_token_path = write_tmp_jwt_file("not_a_valid_json_file");
+ grpc_core::Json credential_source = grpc_core::Json::Parse(
+ absl::StrFormat(
+ "{\n"
+ "\"file\":\"%s\",\n"
+ "\"format\":\n"
+ "{\n"
+ "\"type\":\"json\",\n"
+ "\"subject_token_field_name\":\"access_token\"\n"
+ "}\n"
+ "}",
+ 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;
+ };
+ auto creds =
+ grpc_core::FileExternalAccountCredentials::Create(options, {}, &error);
+ GPR_ASSERT(creds != nullptr);
+ GPR_ASSERT(error == GRPC_ERROR_NONE);
+ grpc_httpcli_set_override(httpcli_get_should_not_be_called,
+ httpcli_post_should_not_be_called);
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "The content of the file is not a valid json object.");
+ grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ "Error occurred when fetching oauth2 token.", &error, 1);
+ request_metadata_state* state =
+ make_request_metadata_state(expected_error, nullptr, 0);
+ run_request_metadata_test(creds.get(), auth_md_ctx, state);
+ grpc_core::ExecCtx::Get()->Flush();
+ grpc_httpcli_set_override(nullptr, nullptr);
+ GRPC_ERROR_UNREF(error);
+ gpr_free(subject_token_path);
+}
+
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
grpc_init();
@@ -2377,12 +2561,16 @@ int main(int argc, char** argv) {
test_auth_metadata_context();
test_external_account_creds_success();
test_external_account_creds_success_with_service_account_impersonation();
- test_external_account_creds_faiure_invalid_token_url();
- test_external_account_creds_faiure_invalid_service_account_impersonation_url();
- test_external_account_creds_faiure_token_exchange_response_missing_access_token();
+ test_external_account_creds_failure_invalid_token_url();
+ test_external_account_creds_failure_invalid_service_account_impersonation_url();
+ test_external_account_creds_failure_token_exchange_response_missing_access_token();
test_url_external_account_creds_success_format_text();
test_url_external_account_creds_success_format_json();
- test_url_external_account_creds_faiure_invalid_credential_source_url();
+ test_url_external_account_creds_failure_invalid_credential_source_url();
+ 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();
+ test_file_external_account_creds_failure_invalid_json_content();
grpc_shutdown();
return 0;
}
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index cf1ad97bf19..4bca2c7f459 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1908,6 +1908,8 @@ src/core/lib/security/credentials/credentials.h \
src/core/lib/security/credentials/credentials_metadata.cc \
src/core/lib/security/credentials/external/external_account_credentials.cc \
src/core/lib/security/credentials/external/external_account_credentials.h \
+src/core/lib/security/credentials/external/file_external_account_credentials.cc \
+src/core/lib/security/credentials/external/file_external_account_credentials.h \
src/core/lib/security/credentials/external/url_external_account_credentials.cc \
src/core/lib/security/credentials/external/url_external_account_credentials.h \
src/core/lib/security/credentials/fake/fake_credentials.cc \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index d5a14e7e48f..b3459384268 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1750,6 +1750,8 @@ src/core/lib/security/credentials/credentials.h \
src/core/lib/security/credentials/credentials_metadata.cc \
src/core/lib/security/credentials/external/external_account_credentials.cc \
src/core/lib/security/credentials/external/external_account_credentials.h \
+src/core/lib/security/credentials/external/file_external_account_credentials.cc \
+src/core/lib/security/credentials/external/file_external_account_credentials.h \
src/core/lib/security/credentials/external/url_external_account_credentials.cc \
src/core/lib/security/credentials/external/url_external_account_credentials.h \
src/core/lib/security/credentials/fake/fake_credentials.cc \