| // 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 |