This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new d34f06b5da2 [fix](be): fix BE access to aws under eks pod identity
(#67076)
d34f06b5da2 is described below
commit d34f06b5da25d50282f07fb801c1b426290ab980
Author: Owen Leung <[email protected]>
AuthorDate: Thu Sep 3 15:28:51 2026 +0800
[fix](be): fix BE access to aws under eks pod identity (#67076)
### What problem does this PR solve?
Issue Number: close #66554
**Problem Summary**
Fixes the issue above by forwarding
`AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE` alongside the inline token.
Given a file path, the provider will re-read it before every fetch, so
credentials survive token rotation. ECS, which sets only the inline
variable `AWS_CONTAINER_AUTHORIZATION_TOKEN`, is unaffected.
**Why the aws-sdp-cpp bump**
The `GeneralHTTPCredentialsProvider` does not exist before 1.11.221. The
only container provider available at the currently pinned version is
`TaskRoleCredentialsProvider`, which takes the token as a string and has
no notion of a token file. 1.11.221 is the first version whose
`GeneralHTTPCredentialsProvider` re-reads the token file.
---
be/src/runtime/aws_msk_iam_auth.cpp | 5 +-
be/test/io/s3_client_factory_test.cpp | 207 ++++++++++++++++++++-
be/test/runtime/aws_msk_iam_auth_test.cpp | 54 ++++++
be/test/testutil/container_credentials_endpoint.h | 99 ++++++++++
cloud/test/s3_accessor_mock_test.cpp | 74 ++++++++
common/cpp/aws_common.cpp | 58 ++++++
common/cpp/aws_common.h | 28 +++
.../cpp/custom_aws_credentials_provider_chain.cpp | 50 ++---
.../cpp/obj-client/auth/aws_credential_factory.cpp | 4 +-
common/cpp/test/container_credentials_test_util.h | 131 +++++++++++++
gensrc/proto/cloud.proto | 2 +-
gensrc/thrift/AgentService.thrift | 2 +-
12 files changed, 657 insertions(+), 57 deletions(-)
diff --git a/be/src/runtime/aws_msk_iam_auth.cpp
b/be/src/runtime/aws_msk_iam_auth.cpp
index 6d6292b7b01..863d2789a61 100644
--- a/be/src/runtime/aws_msk_iam_auth.cpp
+++ b/be/src/runtime/aws_msk_iam_auth.cpp
@@ -21,7 +21,6 @@
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/auth/AWSCredentialsProviderChain.h>
#include <aws/core/auth/STSCredentialsProvider.h>
-#include <aws/core/platform/Environment.h>
#include <aws/identity-management/auth/STSAssumeRoleCredentialsProvider.h>
#include <aws/sts/STSClient.h>
#include <aws/sts/model/AssumeRoleRequest.h>
@@ -34,6 +33,7 @@
#include <sstream>
#include "common/logging.h"
+#include "cpp/aws_common.h"
namespace doris {
@@ -51,8 +51,7 @@ std::shared_ptr<Aws::Auth::AWSCredentialsProvider>
AwsMskIamAuth::_create_provid
} else if (provider_upper == "INSTANCE_PROFILE" || provider_upper ==
"INSTANCEPROFILE") {
return
std::make_shared<Aws::Auth::InstanceProfileCredentialsProvider>();
} else if (provider_upper == "CONTAINER" || provider_upper == "ECS") {
- return std::make_shared<Aws::Auth::TaskRoleCredentialsProvider>(
-
Aws::Environment::GetEnv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI").c_str());
+ return create_container_credentials_provider();
} else if (provider_upper == "SYSTEM_PROPERTIES" || provider_upper ==
"SYSTEMPROPERTIES") {
return
std::make_shared<Aws::Auth::ProfileConfigFileAWSCredentialsProvider>();
} else if (provider_upper == "WEB_IDENTITY" || provider_upper ==
"WEBIDENTITY" ||
diff --git a/be/test/io/s3_client_factory_test.cpp
b/be/test/io/s3_client_factory_test.cpp
index 466ca77415c..835b32bdaef 100644
--- a/be/test/io/s3_client_factory_test.cpp
+++ b/be/test/io/s3_client_factory_test.cpp
@@ -16,6 +16,7 @@
// under the License.
#include <aws/core/auth/AWSCredentialsProviderChain.h>
+#include <aws/core/auth/GeneralHTTPCredentialsProvider.h>
#include <aws/core/auth/STSCredentialsProvider.h>
#include <aws/core/client/ClientConfiguration.h>
#include <aws/identity-management/auth/STSAssumeRoleCredentialsProvider.h>
@@ -23,9 +24,11 @@
#include <gtest/gtest.h>
#include <unistd.h>
+#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <fstream>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -34,9 +37,11 @@
#include "common/config.h"
#include "cpp/aws_common.h"
#include "cpp/custom_aws_credentials_provider_chain.h"
+#include "cpp/obj-client/auth/aws_credential_factory.h"
#include "cpp/obj-client/s3_obj_storage_client.h"
#include "cpp/sync_point.h"
#include "io/fs/s3_file_system.h"
+#include "testutil/container_credentials_endpoint.h"
#include "util/s3_rate_limiter_manager.h"
#include "util/s3_uri.h"
#include "util/s3_util.h"
@@ -573,16 +578,15 @@ TEST_F(S3ClientFactoryTest,
AwsCredentialsProviderV2ProviderTypeWithoutRoleArn)
provider),
nullptr);
- const char* old_container_uri =
std::getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI");
- if (old_container_uri == nullptr) {
- setenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
"/v2/credentials/mock", 1);
- }
- S3ClientConf container_conf;
- container_conf.cred_provider_type = CredProviderType::Container;
- provider =
factory.create_aws_credentials_provider(container_conf).provider;
-
ASSERT_NE(std::dynamic_pointer_cast<Aws::Auth::TaskRoleCredentialsProvider>(provider),
nullptr);
- if (old_container_uri == nullptr) {
- unsetenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI");
+ {
+ // The environment is pinned rather than merely topped up, so that
this case asserts the
+ // same thing whether or not the machine running it happens to be
inside a container.
+ ContainerCredentialsEnvGuard env;
+ env.set_ecs_task_role("/v2/credentials/mock");
+ S3ClientConf container_conf;
+ container_conf.cred_provider_type = CredProviderType::Container;
+ provider =
factory.create_aws_credentials_provider(container_conf).provider;
+ ASSERT_NE(as_valid_http_provider(provider), nullptr);
}
S3ClientConf instance_profile_conf;
@@ -689,4 +693,187 @@ TEST_F(S3ClientFactoryTest,
AwsCredentialsProviderV1PartialCredentialsUseDefault
config::aws_credentials_provider_version = "v2";
}
+namespace {
+
+// The provider is looked up inside the chain rather than constructed directly,
+// because what is under test is how CustomAwsCredentialsProviderChain wires
the
+// environment.
+Aws::Auth::GeneralHTTPCredentialsProvider* find_http_provider(
+ const CustomAwsCredentialsProviderChain& chain) {
+ for (const auto& provider : chain.GetProviders()) {
+ auto* http_provider =
+
dynamic_cast<Aws::Auth::GeneralHTTPCredentialsProvider*>(provider.get());
+ if (http_provider != nullptr) {
+ return http_provider;
+ }
+ }
+ return nullptr;
+}
+
+} // namespace
+
+// EKS Pod Identity supplies the credential-endpoint token as a file that the
+// kubelet rotates in place, and never as a plain environment variable. The
chain
+// must therefore hand the provider the token path, so that every refresh picks
+// up the current contents. Passing the value read at construction time works
+// until the first rotation and then fails with AccessDenied.
+TEST_F(S3ClientFactoryTest, CustomChainReadsRotatedTokenFileForPodIdentity) {
+ (void)S3ClientFactory::instance();
+
+ ContainerCredentialsEndpoint endpoint;
+ ASSERT_TRUE(endpoint.start());
+
+ ContainerCredentialsEnvGuard env;
+ const std::string token_path = env.token_file_path("custom_chain");
+ env.write_token_file(token_path, "token-one");
+ env.set_pod_identity(endpoint.url(), token_path);
+
+ CustomAwsCredentialsProviderChain chain;
+ auto* provider = find_http_provider(chain);
+ ASSERT_NE(provider, nullptr) << "no GeneralHTTPCredentialsProvider was
added to the chain";
+
+ // Each GetAWSCredentials() drives one HTTP GET to the endpoint: the
provider re-reads the token
+ // file, sends it as the Authorization header, and parses the credentials
from the reply. The
+ // handler records the header it saw, so auth_headers() reports what
actually went over the wire.
+ const auto first_credentials = provider->GetAWSCredentials();
+ EXPECT_EQ(first_credentials.GetAWSAccessKeyId(), "AKIDTEST");
+ EXPECT_EQ(first_credentials.GetSessionToken(), "SESSIONTEST");
+
+ // Rotate the file the way the kubelet does. The second call refetches
rather than serving its
+ // cache only because the handler reports an already-expired Expiration.
+ env.write_token_file(token_path, "token-two");
+ provider->GetAWSCredentials();
+
+ // GE rather than EQ: the credentials client retries and the handler
records every attempt, so an
+ // exact count would make a retry look like a bug. front/back keep the
assertion at full strength
+ // because every request before the rewrite carries token-one and every
one after carries token-two.
+ const auto auth_headers = endpoint.auth_headers();
+ ASSERT_GE(auth_headers.size(), 2u);
+ EXPECT_EQ(auth_headers.front(), "token-one");
+ EXPECT_EQ(auth_headers.back(), "token-two");
+}
+
+// The same wiring has to hold when CONTAINER is asked for by name rather than
reached through the
+// default chain, which is the whole point of a public provider mode. Reading
only
+// AWS_CONTAINER_CREDENTIALS_RELATIVE_URI leaves this provider with an empty
URI, no HTTP client and
+// no credentials on every standard EKS deployment.
+TEST_F(S3ClientFactoryTest,
ContainerProviderTypeReadsRotatedTokenFileForPodIdentity) {
+ S3ClientFactory& factory = S3ClientFactory::instance();
+ config::aws_credentials_provider_version = "v2";
+
+ ContainerCredentialsEndpoint endpoint;
+ ASSERT_TRUE(endpoint.start());
+
+ ContainerCredentialsEnvGuard env;
+ const std::string token_path = env.token_file_path("container_type");
+ env.write_token_file(token_path, "token-one");
+ env.set_pod_identity(endpoint.url(), token_path);
+
+ S3ClientConf conf;
+ conf.cred_provider_type = CredProviderType::Container;
+ auto provider =
as_valid_http_provider(factory.create_aws_credentials_provider(conf).provider);
+ ASSERT_NE(provider, nullptr) << "CONTAINER did not yield a usable
container credentials "
+ "provider for
AWS_CONTAINER_CREDENTIALS_FULL_URI";
+
+ const auto first_credentials = provider->GetAWSCredentials();
+ EXPECT_EQ(first_credentials.GetAWSAccessKeyId(), "AKIDTEST");
+ EXPECT_EQ(first_credentials.GetSessionToken(), "SESSIONTEST");
+
+ env.write_token_file(token_path, "token-two");
+ provider->GetAWSCredentials();
+
+ const auto auth_headers = endpoint.auth_headers();
+ ASSERT_GE(auth_headers.size(), 2u);
+ EXPECT_EQ(auth_headers.front(), "token-one");
+ EXPECT_EQ(auth_headers.back(), "token-two");
+}
+
+TEST_F(S3ClientFactoryTest,
ContainerProviderTypeForwardsInlineAuthorizationToken) {
+ S3ClientFactory& factory = S3ClientFactory::instance();
+ config::aws_credentials_provider_version = "v2";
+
+ ContainerCredentialsEndpoint endpoint;
+ ASSERT_TRUE(endpoint.start());
+
+ ContainerCredentialsEnvGuard env;
+ env.set_inline_token_endpoint(endpoint.url(), "inline-token");
+
+ S3ClientConf conf;
+ conf.cred_provider_type = CredProviderType::Container;
+ auto provider =
as_valid_http_provider(factory.create_aws_credentials_provider(conf).provider);
+ ASSERT_NE(provider, nullptr) << "CONTAINER did not yield a usable
container credentials "
+ "provider for an inline authorization
token";
+
+ EXPECT_EQ(provider->GetAWSCredentials().GetAWSAccessKeyId(), "AKIDTEST");
+
+ const auto auth_headers = endpoint.auth_headers();
+ ASSERT_GE(auth_headers.size(), 1u);
+ EXPECT_EQ(auth_headers.front(), "inline-token");
+}
+
+TEST_F(S3ClientFactoryTest, ContainerProviderTypeStillHonoursEcsRelativeUri) {
+ S3ClientFactory& factory = S3ClientFactory::instance();
+ config::aws_credentials_provider_version = "v2";
+
+ ContainerCredentialsEnvGuard env;
+ env.set_ecs_task_role("/v2/credentials/mock");
+
+ S3ClientConf conf;
+ conf.cred_provider_type = CredProviderType::Container;
+
EXPECT_NE(as_valid_http_provider(factory.create_aws_credentials_provider(conf).provider),
+ nullptr)
+ << "CONTAINER did not yield a usable container credentials
provider for "
+ "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
+}
+
+// With neither URI exported there is nothing to talk to, and the provider
says so. This pins the
+// discriminator the two tests above rely on: IsValid() really does
distinguish a wired provider
+// from an inert one, so their assertions cannot pass vacuously.
+TEST_F(S3ClientFactoryTest, ContainerProviderTypeIsUnusableWithoutAnyUri) {
+ S3ClientFactory& factory = S3ClientFactory::instance();
+ config::aws_credentials_provider_version = "v2";
+
+ // Constructing the guard is the whole setup: it clears all four
AWS_CONTAINER_* variables, so
+ // this runs as if on a host that is not a container at all.
+ ContainerCredentialsEnvGuard env;
+
+ S3ClientConf conf;
+ conf.cred_provider_type = CredProviderType::Container;
+ auto provider = factory.create_aws_credentials_provider(conf).provider;
+
ASSERT_NE(std::dynamic_pointer_cast<Aws::Auth::GeneralHTTPCredentialsProvider>(provider),
+ nullptr);
+ EXPECT_EQ(as_valid_http_provider(provider), nullptr);
+}
+
+// With a role_arn the CONTAINER provider is not handed to the S3 client
directly: it becomes the
+// base provider the STS client authenticates its AssumeRole call with.
AwsCredentialFactory is
+// asked for that base provider here - a v2 request with no role_arn returns
it unwrapped - so the
+// assertion is about the base itself rather than the STS wrapper around it.
+TEST_F(S3ClientFactoryTest, ContainerProviderTypeIsUsableAsStsBaseProvider) {
+ (void)S3ClientFactory::instance();
+
+ ContainerCredentialsEndpoint endpoint;
+ ASSERT_TRUE(endpoint.start());
+
+ ContainerCredentialsEnvGuard env;
+ const std::string token_path = env.token_file_path("sts_base");
+ env.write_token_file(token_path, "token-one");
+ env.set_pod_identity(endpoint.url(), token_path);
+
+ AwsCredentialOptions options;
+ options.version = AwsCredentialProviderVersion::V2;
+ options.provider_type = CredProviderType::Container;
+ // role_arn stays empty on purpose: that is what makes create() hand back
the base provider
+ // itself instead of the STS wrapper built on top of it.
+ auto base_provider =
as_valid_http_provider(AwsCredentialFactory::create(options).provider);
+ ASSERT_NE(base_provider, nullptr)
+ << "CONTAINER did not yield a usable STS base credentials
provider";
+
+ EXPECT_EQ(base_provider->GetAWSCredentials().GetAWSAccessKeyId(),
"AKIDTEST");
+ const auto auth_headers = endpoint.auth_headers();
+ ASSERT_FALSE(auth_headers.empty())
+ << "the STS base provider never contacted the credentials
endpoint";
+ EXPECT_EQ(auth_headers.back(), "token-one");
+}
+
} // namespace doris
diff --git a/be/test/runtime/aws_msk_iam_auth_test.cpp
b/be/test/runtime/aws_msk_iam_auth_test.cpp
index f1eb1ec37ed..954621ece5e 100644
--- a/be/test/runtime/aws_msk_iam_auth_test.cpp
+++ b/be/test/runtime/aws_msk_iam_auth_test.cpp
@@ -17,6 +17,7 @@
#include "runtime/aws_msk_iam_auth.h"
+#include <aws/core/auth/AWSCredentials.h>
#include <gtest/gtest.h>
#include <memory>
@@ -24,6 +25,8 @@
#include <unordered_map>
#include "common/status.h"
+#include "testutil/container_credentials_endpoint.h"
+#include "util/s3_util.h"
namespace doris {
@@ -34,6 +37,14 @@ protected:
config.region = "us-east-1";
}
+ // Nothing in this binary initialises the AWS SDK on its own - neither
BE-UT's main() nor this
+ // file - and without Aws::InitAPI there is no HTTP client factory, so a
credentials provider
+ // quietly returns nothing instead of making a request. Constructing the
S3 client factory is
+ // the cheapest in-tree way to get InitAPI called, exactly once per
process, and it is the same
+ // trick the S3 client factory tests use. Only the tests that drive a real
fetch need it, so it
+ // stays out of SetUp() where it would change what the older tests in this
file do.
+ static void ensure_aws_sdk_initialized() {
(void)S3ClientFactory::instance(); }
+
AwsMskIamAuth::Config config;
};
@@ -215,6 +226,49 @@ TEST_F(AwsMskIamAuthTest,
TestOAuthCallbackCreationWithExternalIdWithoutRoleArn)
ASSERT_EQ(callback, nullptr);
}
+TEST_F(AwsMskIamAuthTest, ContainerProviderReadsTokenFileForPodIdentity) {
+ ensure_aws_sdk_initialized();
+
+ ContainerCredentialsEndpoint endpoint;
+ ASSERT_TRUE(endpoint.start());
+
+ ContainerCredentialsEnvGuard env;
+ const std::string token_path = env.token_file_path("msk_container");
+ env.write_token_file(token_path, "token-one");
+ env.set_pod_identity(endpoint.url(), token_path);
+
+ config.credentials_provider = "CONTAINER";
+ AwsMskIamAuth auth(config);
+
+ Aws::Auth::AWSCredentials credentials;
+ ASSERT_TRUE(auth.get_credentials(&credentials).ok());
+ EXPECT_EQ(credentials.GetAWSAccessKeyId(), "AKIDTEST");
+ EXPECT_EQ(credentials.GetSessionToken(), "SESSIONTEST");
+
+ const auto auth_headers = endpoint.auth_headers();
+ ASSERT_FALSE(auth_headers.empty());
+ EXPECT_EQ(auth_headers.back(), "token-one");
+}
+
+TEST_F(AwsMskIamAuthTest, EcsProviderAliasReachesContainerCredentialsEndpoint)
{
+ ensure_aws_sdk_initialized();
+
+ ContainerCredentialsEndpoint endpoint;
+ ASSERT_TRUE(endpoint.start());
+
+ ContainerCredentialsEnvGuard env;
+ const std::string token_path = env.token_file_path("msk_ecs_alias");
+ env.write_token_file(token_path, "token-one");
+ env.set_pod_identity(endpoint.url(), token_path);
+
+ config.credentials_provider = "ECS";
+ AwsMskIamAuth auth(config);
+
+ Aws::Auth::AWSCredentials credentials;
+ ASSERT_TRUE(auth.get_credentials(&credentials).ok());
+ EXPECT_EQ(credentials.GetAWSAccessKeyId(), "AKIDTEST");
+}
+
// Integration test - only runs if AWS credentials are available
TEST_F(AwsMskIamAuthTest, DISABLED_IntegrationTestWithRealCredentials) {
// This test is disabled by default
diff --git a/be/test/testutil/container_credentials_endpoint.h
b/be/test/testutil/container_credentials_endpoint.h
new file mode 100644
index 00000000000..ac60189a69e
--- /dev/null
+++ b/be/test/testutil/container_credentials_endpoint.h
@@ -0,0 +1,99 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+#pragma once
+
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "cpp/test/container_credentials_test_util.h"
+#include "service/http/ev_http_server.h"
+#include "service/http/http_channel.h"
+#include "service/http/http_handler.h"
+#include "service/http/http_headers.h"
+#include "service/http/http_method.h"
+#include "service/http/http_request.h"
+
+// Scaffolding for tests of the container credentials providers - the ECS
task-role and EKS Pod
+// Identity endpoints. A credible test needs three awkward pieces at once: a
real HTTP endpoint on an
+// address the AWS SDK is willing to talk to, a token file that can be
rewritten mid-test, and the
+// four AWS_CONTAINER_* environment variables put back however they were found.
+//
+// Only the first of those lives here, because it is the only one the cloud
test tree cannot use: it
+// needs EvHttpServer, which is BE-only. The other two -
ContainerCredentialsEnvGuard and
+// as_valid_http_provider - come from
cpp/test/container_credentials_test_util.h, included above and
+// re-exported to anything that includes this header, so BE tests keep getting
all three from one
+// include.
+namespace doris {
+
+// A mock of the credentials endpoint that ECS and the EKS Pod Identity agent
expose.
+class ContainerCredentialsHandler : public HttpHandler {
+public:
+ void handle(HttpRequest* req) override {
+ {
+ std::lock_guard<std::mutex> lock(_mutex);
+ _auth_headers.push_back(req->header(HttpHeaders::AUTHORIZATION));
+ }
+
+ req->add_output_header(HttpHeaders::CONTENT_TYPE, "application/json");
+ // Expiration in the past keeps ExpiresSoon() true, so the provider
+ // re-reads the token file on the next call instead of serving its
cache.
+ HttpChannel::send_reply(req,
+
R"({"AccessKeyId":"AKIDTEST","SecretAccessKey":"SECRETTEST",)"
+
R"("Token":"SESSIONTEST","Expiration":"1970-01-01T00:00:00Z"})");
+ }
+
+ std::vector<std::string> auth_headers() {
+ std::lock_guard<std::mutex> lock(_mutex);
+ return _auth_headers;
+ }
+
+private:
+ std::mutex _mutex;
+ std::vector<std::string> _auth_headers;
+};
+
+// Starts the mock endpoint on an OS-assigned loopback port and hands out its
URL.
+class ContainerCredentialsEndpoint {
+public:
+ bool start() {
+ if (!_server.register_handler(GET, "/creds", &_handler)) {
+ return false;
+ }
+ _server.start();
+ if (_server.get_real_port() == 0) {
+ return false;
+ }
+ _url = "http://127.0.0.1:" + std::to_string(_server.get_real_port()) +
"/creds";
+ return true;
+ }
+
+ const std::string& url() const { return _url; }
+
+ std::vector<std::string> auth_headers() { return _handler.auth_headers(); }
+
+private:
+ // _handler is declared before _server so that it is destroyed after it:
~EvHttpServer() stops
+ // the server, and stop() only returns once every worker thread has left
its event loop, so no
+ // request can still be inside _handler by then.
+ ContainerCredentialsHandler _handler;
+ EvHttpServer _server {0};
+ std::string _url;
+};
+
+} // namespace doris
diff --git a/cloud/test/s3_accessor_mock_test.cpp
b/cloud/test/s3_accessor_mock_test.cpp
index 30624e82649..5e9d985777e 100644
--- a/cloud/test/s3_accessor_mock_test.cpp
+++ b/cloud/test/s3_accessor_mock_test.cpp
@@ -16,6 +16,7 @@
// under the License.
#include <aws/core/Aws.h>
+#include <aws/core/auth/GeneralHTTPCredentialsProvider.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/ListObjectsV2Request.h>
#include <aws/s3/model/ListObjectsV2Result.h>
@@ -23,10 +24,17 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <cstdio>
+#include <memory>
+#include <string>
+
#include "common/config.h"
#include "common/logging.h"
+#include "cpp/aws_common.h"
#include "cpp/obj-client/s3_obj_storage_client.h"
#include "cpp/sync_point.h"
+#include "cpp/test/container_credentials_test_util.h"
+#include "recycler/s3_accessor.h"
using namespace doris;
using namespace Aws::S3::Model;
@@ -86,4 +94,70 @@ TEST_F(S3AccessorMockTest, list_objects_compatibility) {
EXPECT_TRUE(objects.empty());
}
+namespace {
+
+class ProviderProbe : public S3Accessor {
+public:
+ ProviderProbe() : S3Accessor(S3Conf {}) {}
+
+ // The recycler builds its provider through
create_aws_credentials_provider(), so the probe goes
+ // through the same call rather than reaching past it. An S3Conf with no
ak/sk and no role_arn is
+ // what a vault configured for container credentials looks like, and it
makes the factory return
+ // the CONTAINER base provider unwrapped.
+ std::shared_ptr<Aws::Auth::AWSCredentialsProvider> container_provider() {
+ S3Conf conf;
+ conf.cred_provider_type = CredProviderType::Container;
+ return create_aws_credentials_provider(conf).provider;
+ }
+};
+
+} // namespace
+
+// The recycler reaches CredProviderType::Container through a storage vault's
persisted
+// cred_provider_type, and on EKS the pod's credentials live behind
+// AWS_CONTAINER_CREDENTIALS_FULL_URI with the token in a kubelet-rotated
file. Reading only
+// AWS_CONTAINER_CREDENTIALS_RELATIVE_URI leaves this provider with no
endpoint, so recycling silently
+// reclaims nothing.
+TEST_F(S3AccessorMockTest,
container_provider_uses_pod_identity_full_uri_and_token_file) {
+ ContainerCredentialsEnvGuard env;
+ const std::string token_path = env.token_file_path("cloud_pod_identity");
+ env.write_token_file(token_path, "token-one");
+ env.set_pod_identity("http://127.0.0.1:65000/creds", token_path);
+
+ ProviderProbe probe;
+ EXPECT_NE(as_valid_http_provider(probe.container_provider()), nullptr)
+ << "CONTAINER did not yield a usable container credentials
provider for "
+ "AWS_CONTAINER_CREDENTIALS_FULL_URI";
+
+ ASSERT_EQ(std::remove(token_path.c_str()), 0);
+ EXPECT_EQ(as_valid_http_provider(probe.container_provider()), nullptr)
+ << "CONTAINER ignored AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: the
provider stayed "
+ "valid "
+ "with the token file removed, so the path was never forwarded";
+}
+
+// ECS is the other half of the same provider mode: forwarding the full URI
must not cost the
+// relative one, which the provider resolves against the ECS agent's own
address.
+TEST_F(S3AccessorMockTest, container_provider_still_honours_ecs_relative_uri) {
+ ContainerCredentialsEnvGuard env;
+ env.set_ecs_task_role("/v2/credentials/mock");
+
+ ProviderProbe probe;
+ EXPECT_NE(as_valid_http_provider(probe.container_provider()), nullptr)
+ << "CONTAINER did not yield a usable container credentials
provider for "
+ "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
+}
+
+// Pins the discriminator the two tests above rely on: with neither URI
exported the provider really
+// is unusable, so their assertions cannot be passing vacuously.
+TEST_F(S3AccessorMockTest, container_provider_is_unusable_without_any_uri) {
+ ContainerCredentialsEnvGuard env;
+
+ ProviderProbe probe;
+ auto provider = probe.container_provider();
+
ASSERT_NE(std::dynamic_pointer_cast<Aws::Auth::GeneralHTTPCredentialsProvider>(provider),
+ nullptr);
+ EXPECT_EQ(as_valid_http_provider(provider), nullptr);
+}
+
} // namespace doris::cloud
diff --git a/common/cpp/aws_common.cpp b/common/cpp/aws_common.cpp
index 7f11d8cb95e..41dc9debaca 100644
--- a/common/cpp/aws_common.cpp
+++ b/common/cpp/aws_common.cpp
@@ -17,11 +17,18 @@
#include "aws_common.h"
+#include <aws/core/auth/GeneralHTTPCredentialsProvider.h>
#include <aws/core/client/ClientConfiguration.h>
+#include <aws/core/platform/Environment.h>
+#include <aws/core/utils/memory/AWSMemory.h>
#include <glog/logging.h>
namespace doris {
+namespace {
+const char CONTAINER_CREDENTIALS_PROVIDER_TAG[] =
"ContainerCredentialsProvider";
+} // namespace
+
CredProviderType cred_provider_type_from_pb(cloud::CredProviderTypePB
cred_provider_type) {
switch (cred_provider_type) {
case cloud::CredProviderTypePB::DEFAULT:
@@ -77,6 +84,57 @@ CredProviderType cred_provider_type_from_string(const
std::string& type) {
return CredProviderType::Default;
}
+bool container_credentials_available() {
+ return
!Aws::Environment::GetEnv(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI).empty() ||
+
!Aws::Environment::GetEnv(AWS_CONTAINER_CREDENTIALS_FULL_URI).empty();
+}
+
+std::shared_ptr<Aws::Auth::AWSCredentialsProvider>
create_container_credentials_provider() {
+ const auto relative_uri =
Aws::Environment::GetEnv(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
+ const auto absolute_uri =
Aws::Environment::GetEnv(AWS_CONTAINER_CREDENTIALS_FULL_URI);
+ const auto token =
Aws::Environment::GetEnv(AWS_CONTAINER_AUTHORIZATION_TOKEN);
+ const auto token_path =
Aws::Environment::GetEnv(AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE);
+
+ // Both URIs are forwarded and the provider decides between them: a
non-empty relative URI wins
+ // and is resolved against the ECS agent's address, otherwise the full URI
is used as-is. This
+ // is the same precedence the AWS SDK's own default chain applies.
+ //
+ // Both token forms are forwarded for the same reason. The endpoint
authenticates every fetch
+ // with a bearer token, which the provider takes either inline or as a
file path, and given a
+ // path it re-reads the file before each fetch. ECS sets only the inline
variable, EKS Pod
+ // Identity sets only the file one - so forwarding the path is what makes
the Authorization header
+ // non-empty under Pod Identity, and what keeps it valid once the kubelet
rotates the file.
+ //
+ // NOTE: The header file names its third parameter authTokenFilePath and
its fourth authToken,
+ // but the implementation binds them the other way round. The header is
the side that is wrong,
+ // not the definition. This is reported as aws/aws-sdk-cpp#3143, fixed by
+ // aws/aws-sdk-cpp#3162.
+ auto provider = Aws::MakeShared<Aws::Auth::GeneralHTTPCredentialsProvider>(
+ CONTAINER_CREDENTIALS_PROVIDER_TAG, relative_uri, absolute_uri,
token, token_path);
+
+ const bool uses_relative_uri = !relative_uri.empty();
+ const char* const uri_var = uses_relative_uri ?
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
+ :
AWS_CONTAINER_CREDENTIALS_FULL_URI;
+ const auto& uri = uses_relative_uri ? relative_uri : absolute_uri;
+
+ if (relative_uri.empty() && absolute_uri.empty()) {
+ LOG(WARNING) << "Container credentials provider has no endpoint to
call and will return no "
+ "credentials: neither "
+ << AWS_CONTAINER_CREDENTIALS_RELATIVE_URI << " nor "
+ << AWS_CONTAINER_CREDENTIALS_FULL_URI << " is set.";
+ } else {
+ LOG(INFO)
+ << "Created container credentials provider from " << uri_var
<< ": [" << uri
+ << "] with a" << (token.empty() ? "n empty" : " non-empty")
+ << " inline authorization token and a"
+ << (token_path.empty() ? "n empty" : " non-empty")
+ << " authorization token file path: [" << token_path
+ << "]. If credentials come back empty, raise aws_log_level to
3 or higher for the "
+ "SDK's own reason.";
+ }
+ return provider;
+}
+
std::string get_valid_ca_cert_path(const std::vector<std::string>&
ca_cert_file_paths) {
for (const auto& path : ca_cert_file_paths) {
if (std::filesystem::exists(path)) {
diff --git a/common/cpp/aws_common.h b/common/cpp/aws_common.h
index d977dd245b0..9c48ca5133e 100644
--- a/common/cpp/aws_common.h
+++ b/common/cpp/aws_common.h
@@ -20,6 +20,11 @@
#include <gen_cpp/cloud.pb.h>
#include <filesystem>
+#include <memory>
+
+namespace Aws::Auth {
+class AWSCredentialsProvider;
+}
namespace Aws::Client {
struct ClientConfiguration;
@@ -38,10 +43,33 @@ enum class CredProviderType {
Anonymous = 7
};
+// The environment variables through which a container runtime advertises its
credentials
+// endpoint. ECS exports a relative URI, which is a path resolved against the
ECS agent's fixed
+// link-local address, and optionally an inline authorization token. EKS Pod
Identity exports a
+// full URI, which is a complete URL, and an authorization token file that the
kubelet rotates in
+// place. A runtime never sets both URIs, so code that reads only one of them
silently gets
+// nothing on the other platform.
+inline constexpr char AWS_CONTAINER_CREDENTIALS_RELATIVE_URI[] =
+ "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
+inline constexpr char AWS_CONTAINER_CREDENTIALS_FULL_URI[] =
"AWS_CONTAINER_CREDENTIALS_FULL_URI";
+inline constexpr char AWS_CONTAINER_AUTHORIZATION_TOKEN[] =
"AWS_CONTAINER_AUTHORIZATION_TOKEN";
+inline constexpr char AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE[] =
+ "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE";
+
CredProviderType cred_provider_type_from_pb(cloud::CredProviderTypePB
cred_provider_type);
CredProviderType cred_provider_type_from_string(const std::string& type);
+// Builds the credentials provider that talks to a container runtime's
credentials endpoint, from
+// the four AWS_CONTAINER_* environment variables above. Every caller that
asks for container credentials
+// - the default provider chain, and the explicit CONTAINER/ECS provider modes
of the BE S3 client
+// factory, the cloud recycler and the Kafka MSK IAM signer - has to support
both ECS and EKS Pod
+// Identity, so none of them can afford to read a subset of the variables.
+std::shared_ptr<Aws::Auth::AWSCredentialsProvider>
create_container_credentials_provider();
+
+// True when the runtime advertises a container credentials endpoint through
either URI variable.
+bool container_credentials_available();
+
std::string get_valid_ca_cert_path(const std::vector<std::string>&
ca_cert_file_paths);
// Configures the default S3 client transport scheme for endpoints without an
explicit scheme.
diff --git a/common/cpp/custom_aws_credentials_provider_chain.cpp
b/common/cpp/custom_aws_credentials_provider_chain.cpp
index 5b8ae485bd8..6727136d751 100644
--- a/common/cpp/custom_aws_credentials_provider_chain.cpp
+++ b/common/cpp/custom_aws_credentials_provider_chain.cpp
@@ -18,72 +18,44 @@
#include "custom_aws_credentials_provider_chain.h"
#include <aws/core/auth/AWSCredentialsProviderChain.h>
-#include <aws/core/auth/STSCredentialsProvider.h>
#include <aws/core/auth/SSOCredentialsProvider.h>
+#include <aws/core/auth/STSCredentialsProvider.h>
#include <aws/core/platform/Environment.h>
-#include <aws/core/utils/memory/AWSMemory.h>
#include <aws/core/utils/StringUtils.h>
#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/memory/AWSMemory.h>
+
+#include "aws_common.h"
namespace doris {
using namespace Aws::Auth;
using namespace Aws::Utils::Threading;
-static const char AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI[] =
- "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
-static const char AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI[] =
"AWS_CONTAINER_CREDENTIALS_FULL_URI";
-static const char AWS_ECS_CONTAINER_AUTHORIZATION_TOKEN[] =
"AWS_CONTAINER_AUTHORIZATION_TOKEN";
static const char AWS_EC2_METADATA_DISABLED[] = "AWS_EC2_METADATA_DISABLED";
static const char DefaultCredentialsProviderChainTag[] =
"DefaultAWSCredentialsProviderChain";
CustomAwsCredentialsProviderChain::CustomAwsCredentialsProviderChain()
: AWSCredentialsProviderChain() {
-
AddProvider(Aws::MakeShared<STSAssumeRoleWebIdentityCredentialsProvider>(
DefaultCredentialsProviderChainTag));
- //ECS TaskRole Credentials only available when ENVIRONMENT VARIABLE is set
- const auto relativeUri =
Aws::Environment::GetEnv(AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI);
- AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag,
- "The environment variable value "
- << AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI
<< " is "
- << relativeUri);
-
- const auto absoluteUri =
Aws::Environment::GetEnv(AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI);
- AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag,
- "The environment variable value " <<
AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI
- << " is " <<
absoluteUri);
-
const auto ec2MetadataDisabled =
Aws::Environment::GetEnv(AWS_EC2_METADATA_DISABLED);
AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag,
"The environment variable value " <<
AWS_EC2_METADATA_DISABLED << " is "
<<
ec2MetadataDisabled);
- if (!relativeUri.empty()) {
-
AddProvider(Aws::MakeShared<TaskRoleCredentialsProvider>(DefaultCredentialsProviderChainTag,
-
relativeUri.c_str()));
- AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag,
- "Added ECS metadata service credentials provider
with relative path: ["
- << relativeUri << "] to the provider
chain.");
- } else if (!absoluteUri.empty()) {
- const auto token =
Aws::Environment::GetEnv(AWS_ECS_CONTAINER_AUTHORIZATION_TOKEN);
- AddProvider(Aws::MakeShared<TaskRoleCredentialsProvider>(
- DefaultCredentialsProviderChainTag, absoluteUri.c_str(),
token.c_str()));
-
- //DO NOT log the value of the authorization token for security
purposes.
- AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag,
- "Added ECS credentials provider with URI: ["
- << absoluteUri << "] to the provider chain
with a"
- << (token.empty() ? "n empty " : "
non-empty ")
- << "authorization token.");
+ // One provider serves both container platforms:
create_container_credentials_provider() reads
+ // all four AWS_CONTAINER_* variables, applies the provider's own
relative-then-absolute
+ // precedence, and logs which variable supplied the endpoint.
+ if (container_credentials_available()) {
+ AddProvider(create_container_credentials_provider());
}
AddProvider(Aws::MakeShared<InstanceProfileCredentialsProvider>(
DefaultCredentialsProviderChainTag));
- AWS_LOGSTREAM_INFO(
- DefaultCredentialsProviderChainTag,
- "Added EC2 metadata service credentials provider to the provider
chain.");
+ AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag,
+ "Added EC2 metadata service credentials provider to the
provider chain.");
AddProvider(
Aws::MakeShared<EnvironmentAWSCredentialsProvider>(DefaultCredentialsProviderChainTag));
diff --git a/common/cpp/obj-client/auth/aws_credential_factory.cpp
b/common/cpp/obj-client/auth/aws_credential_factory.cpp
index f8d47411b34..8c49b4bd728 100644
--- a/common/cpp/obj-client/auth/aws_credential_factory.cpp
+++ b/common/cpp/obj-client/auth/aws_credential_factory.cpp
@@ -21,7 +21,6 @@
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/auth/AWSCredentialsProviderChain.h>
#include <aws/core/auth/STSCredentialsProvider.h>
-#include <aws/core/platform/Environment.h>
#include <aws/identity-management/auth/STSAssumeRoleCredentialsProvider.h>
#include <aws/sts/STSClient.h>
@@ -41,8 +40,7 @@ std::shared_ptr<Provider>
create_v2_base_provider(CredProviderType type) {
case CredProviderType::WebIdentity:
return
std::make_shared<Aws::Auth::STSAssumeRoleWebIdentityCredentialsProvider>();
case CredProviderType::Container:
- return std::make_shared<Aws::Auth::TaskRoleCredentialsProvider>(
-
Aws::Environment::GetEnv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI").c_str());
+ return create_container_credentials_provider();
case CredProviderType::Anonymous:
return std::make_shared<Aws::Auth::AnonymousAWSCredentialsProvider>();
case CredProviderType::Default:
diff --git a/common/cpp/test/container_credentials_test_util.h
b/common/cpp/test/container_credentials_test_util.h
new file mode 100644
index 00000000000..e76d038bc6a
--- /dev/null
+++ b/common/cpp/test/container_credentials_test_util.h
@@ -0,0 +1,131 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+#pragma once
+
+#include <aws/core/auth/AWSCredentialsProvider.h>
+#include <aws/core/auth/GeneralHTTPCredentialsProvider.h>
+#include <unistd.h>
+
+#include <array>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <fstream>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+#include "cpp/aws_common.h"
+
+// Test support for the container credentials provider built by
+// create_container_credentials_provider(). It lives in common/cpp/test
because both test trees need
+// it and neither can include the other's: the BE unit tests cover the S3
client factory and the
+// Kafka MSK IAM signer, the cloud unit tests cover the recycler, and all
three reach the same
+// factory.
+namespace doris {
+
+// Clears the four AWS_CONTAINER_* variables on construction and restores them
on destruction.
+class ContainerCredentialsEnvGuard {
+public:
+ ContainerCredentialsEnvGuard() {
+ for (const char* name : kNames) {
+ const char* value = std::getenv(name);
+ _saved.emplace_back(value == nullptr ? std::nullopt
+ :
std::optional<std::string>(value));
+ unsetenv(name);
+ }
+ }
+
+ ~ContainerCredentialsEnvGuard() {
+ for (size_t i = 0; i < kNames.size(); ++i) {
+ if (_saved[i].has_value()) {
+ setenv(kNames[i], _saved[i]->c_str(), 1);
+ } else {
+ unsetenv(kNames[i]);
+ }
+ }
+ for (const auto& path : _token_files) {
+ std::remove(path.c_str());
+ }
+ }
+
+ ContainerCredentialsEnvGuard(const ContainerCredentialsEnvGuard&) = delete;
+ ContainerCredentialsEnvGuard& operator=(const
ContainerCredentialsEnvGuard&) = delete;
+
+ // Presents the environment the way EKS Pod Identity does: a full URL, a
token that exists only
+ // as a file, and no relative URI or inline token at all.
+ void set_pod_identity(const std::string& full_uri, const std::string&
token_file) {
+ unsetenv(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
+ unsetenv(AWS_CONTAINER_AUTHORIZATION_TOKEN);
+ setenv(AWS_CONTAINER_CREDENTIALS_FULL_URI, full_uri.c_str(), 1);
+ setenv(AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, token_file.c_str(), 1);
+ }
+
+ // Presents the environment the way ECS does: a relative path against the
agent's own address,
+ // and no full URI or token file.
+ void set_ecs_task_role(const std::string& relative_uri) {
+ unsetenv(AWS_CONTAINER_CREDENTIALS_FULL_URI);
+ unsetenv(AWS_CONTAINER_AUTHORIZATION_TOKEN);
+ unsetenv(AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE);
+ setenv(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, relative_uri.c_str(),
1);
+ }
+
+ void set_inline_token_endpoint(const std::string& full_uri, const
std::string& token) {
+ unsetenv(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
+ unsetenv(AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE);
+ setenv(AWS_CONTAINER_CREDENTIALS_FULL_URI, full_uri.c_str(), 1);
+ setenv(AWS_CONTAINER_AUTHORIZATION_TOKEN, token.c_str(), 1);
+ }
+
+ // Writes a token file and takes responsibility for deleting it. Call it
again with the same path
+ // to rotate the token the way the kubelet does.
+ void write_token_file(const std::string& path, const std::string&
contents) {
+ std::ofstream out(path, std::ios::trunc);
+ out << contents;
+ out.flush();
+ _token_files.push_back(path);
+ }
+
+ // A token file path unique to this test and this process
+ std::string token_file_path(const std::string& name) const {
+ return "/tmp/doris_container_credentials_token_" + name + "_" +
std::to_string(getpid());
+ }
+
+private:
+ static constexpr std::array<const char*, 4> kNames {
+ AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,
AWS_CONTAINER_CREDENTIALS_FULL_URI,
+ AWS_CONTAINER_AUTHORIZATION_TOKEN,
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE};
+
+ std::vector<std::optional<std::string>> _saved;
+ std::vector<std::string> _token_files;
+};
+
+// Returns the provider only if it is a container credentials provider that
can actually reach an
+// endpoint, and nullptr otherwise.
+inline std::shared_ptr<Aws::Auth::GeneralHTTPCredentialsProvider>
as_valid_http_provider(
+ const std::shared_ptr<Aws::Auth::AWSCredentialsProvider>& provider) {
+ auto http_provider =
+
std::dynamic_pointer_cast<Aws::Auth::GeneralHTTPCredentialsProvider>(provider);
+ if (http_provider != nullptr && !http_provider->IsValid()) {
+ return nullptr;
+ }
+ return http_provider;
+}
+
+} // namespace doris
diff --git a/gensrc/proto/cloud.proto b/gensrc/proto/cloud.proto
index 4addf9385b6..a63ac2d5181 100644
--- a/gensrc/proto/cloud.proto
+++ b/gensrc/proto/cloud.proto
@@ -283,7 +283,7 @@ enum CredProviderTypePB {
ENV = 4; // EnvironmentAWSCredentialsProvider
SYSTEM_PROPERTIES = 5; // SystemPropertiesCredentialsProvider
WEB_IDENTITY = 6; // STSAssumeRoleWebIdentityCredentialsProvider
- CONTAINER = 7; // TaskRoleCredentialsProvider
+ CONTAINER = 7; // GeneralHTTPCredentialsProvider, for ECS task roles and
EKS Pod Identity
ANONYMOUS = 8; // AnonymousAWSCredentialsProvider
}
diff --git a/gensrc/thrift/AgentService.thrift
b/gensrc/thrift/AgentService.thrift
index fb5c1a54931..5ca0f531c06 100644
--- a/gensrc/thrift/AgentService.thrift
+++ b/gensrc/thrift/AgentService.thrift
@@ -106,7 +106,7 @@ enum TCredProviderType {
ENV = 3, // EnvironmentAWSCredentialsProvider
SYSTEM_PROPERTIES = 4, // SystemPropertiesCredentialsProvider
WEB_IDENTITY = 5, // STSAssumeRoleWebIdentityCredentialsProvider
- CONTAINER = 6, // TaskRoleCredentialsProvider
+ CONTAINER = 6, // GeneralHTTPCredentialsProvider, for ECS task roles and
EKS Pod Identity
ANONYMOUS = 7 // AnonymousAWSCredentialsProvider
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]