blob: 41dc9debaca83ed21aa9e75dc2b9f1c26a18cdcd [file]
// 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.
#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:
return CredProviderType::Default;
case cloud::CredProviderTypePB::SIMPLE:
return CredProviderType::Simple;
case cloud::CredProviderTypePB::INSTANCE_PROFILE:
return CredProviderType::InstanceProfile;
case cloud::CredProviderTypePB::ENV:
return CredProviderType::Env;
case cloud::CredProviderTypePB::SYSTEM_PROPERTIES:
return CredProviderType::SystemProperties;
case cloud::CredProviderTypePB::WEB_IDENTITY:
return CredProviderType::WebIdentity;
case cloud::CredProviderTypePB::CONTAINER:
return CredProviderType::Container;
case cloud::CredProviderTypePB::ANONYMOUS:
return CredProviderType::Anonymous;
default:
__builtin_unreachable();
LOG(WARNING) << "Invalid CredProviderTypePB value: " << cred_provider_type
<< ", use default instead.";
return CredProviderType::Default;
}
}
CredProviderType cred_provider_type_from_string(const std::string& type) {
if (type.empty() || type == "DEFAULT") {
return CredProviderType::Default;
}
if (type == "SIMPLE") {
return CredProviderType::Simple;
}
if (type == "INSTANCE_PROFILE") {
return CredProviderType::InstanceProfile;
}
if (type == "ENV") {
return CredProviderType::Env;
}
if (type == "SYSTEM_PROPERTIES") {
return CredProviderType::SystemProperties;
}
if (type == "WEB_IDENTITY") {
return CredProviderType::WebIdentity;
}
if (type == "CONTAINER") {
return CredProviderType::Container;
}
if (type == "ANONYMOUS") {
return CredProviderType::Anonymous;
}
LOG(WARNING) << "Unknown credentials provider type: " << type << ", use default instead.";
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)) {
return path;
}
}
return "";
}
void set_s3_client_default_http_scheme(Aws::Client::ClientConfiguration& client_config,
const std::string& scheme) {
if (client_config.endpointOverride.starts_with("http://") ||
client_config.endpointOverride.starts_with("https://")) {
return;
}
client_config.scheme = scheme == "http" ? Aws::Http::Scheme::HTTP : Aws::Http::Scheme::HTTPS;
}
} // namespace doris