LCOV - code coverage report
Current view: top level - source/extensions/common/aws - credentials_provider_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 24 44 54.5 %
Date: 2024-01-05 06:35:25 Functions: 10 16 62.5 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <list>
       4             : #include <optional>
       5             : #include <string>
       6             : 
       7             : #include "envoy/api/api.h"
       8             : #include "envoy/common/optref.h"
       9             : #include "envoy/event/timer.h"
      10             : #include "envoy/http/message.h"
      11             : #include "envoy/server/factory_context.h"
      12             : 
      13             : #include "source/common/common/lock_guard.h"
      14             : #include "source/common/common/logger.h"
      15             : #include "source/common/common/thread.h"
      16             : #include "source/common/init/target_impl.h"
      17             : #include "source/common/protobuf/message_validator_impl.h"
      18             : #include "source/common/protobuf/utility.h"
      19             : #include "source/extensions/common/aws/credentials_provider.h"
      20             : #include "source/extensions/common/aws/metadata_fetcher.h"
      21             : 
      22             : #include "absl/strings/string_view.h"
      23             : 
      24             : namespace Envoy {
      25             : namespace Extensions {
      26             : namespace Common {
      27             : namespace Aws {
      28             : 
      29             : /**
      30             :  *  CreateMetadataFetcherCb is a callback interface for creating a MetadataFetcher instance.
      31             :  */
      32             : using CreateMetadataFetcherCb =
      33             :     std::function<MetadataFetcherPtr(Upstream::ClusterManager&, absl::string_view)>;
      34             : using ServerFactoryContextOptRef = OptRef<Server::Configuration::ServerFactoryContext>;
      35             : 
      36             : /**
      37             :  * Retrieve AWS credentials from the environment variables.
      38             :  *
      39             :  * Adheres to conventions specified in:
      40             :  * https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
      41             :  */
      42             : class EnvironmentCredentialsProvider : public CredentialsProvider,
      43             :                                        public Logger::Loggable<Logger::Id::aws> {
      44             : public:
      45             :   Credentials getCredentials() override;
      46             : };
      47             : 
      48             : class CachedCredentialsProviderBase : public CredentialsProvider,
      49             :                                       public Logger::Loggable<Logger::Id::aws> {
      50             : public:
      51           5 :   Credentials getCredentials() override {
      52           5 :     refreshIfNeeded();
      53           5 :     return cached_credentials_;
      54           5 :   }
      55             : 
      56             : protected:
      57             :   SystemTime last_updated_;
      58             :   Credentials cached_credentials_;
      59             :   Thread::MutexBasicLockable lock_;
      60             : 
      61             :   void refreshIfNeeded();
      62             : 
      63             :   virtual bool needsRefresh() PURE;
      64             :   virtual void refresh() PURE;
      65             : };
      66             : 
      67             : /**
      68             :  * Retrieve AWS credentials from the credentials file.
      69             :  *
      70             :  * Adheres to conventions specified in:
      71             :  * https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html
      72             :  */
      73             : class CredentialsFileCredentialsProvider : public CachedCredentialsProviderBase {
      74             : public:
      75           6 :   CredentialsFileCredentialsProvider(Api::Api& api) : api_(api) {}
      76             : 
      77             : private:
      78             :   Api::Api& api_;
      79             : 
      80             :   bool needsRefresh() override;
      81             :   void refresh() override;
      82             :   void extractCredentials(const std::string& credentials_file, const std::string& profile);
      83             : };
      84             : 
      85             : class MetadataCredentialsProviderBase : public CachedCredentialsProviderBase {
      86             : public:
      87             :   using CurlMetadataFetcher = std::function<absl::optional<std::string>(Http::RequestMessage&)>;
      88             :   using OnAsyncFetchCb = std::function<void(const std::string&&)>;
      89             : 
      90             :   MetadataCredentialsProviderBase(
      91             :       Api::Api& api, ServerFactoryContextOptRef context,
      92             :       const CurlMetadataFetcher& fetch_metadata_using_curl,
      93             :       CreateMetadataFetcherCb create_metadata_fetcher_cb, absl::string_view cluster_name,
      94             :       const envoy::config::cluster::v3::Cluster::DiscoveryType cluster_type, absl::string_view uri);
      95             : 
      96             :   Credentials getCredentials() override;
      97             : 
      98             :   // Get the Metadata credentials cache duration.
      99             :   static std::chrono::seconds getCacheDuration();
     100             : 
     101             : protected:
     102             :   struct ThreadLocalCredentialsCache : public ThreadLocal::ThreadLocalObject {
     103           6 :     ThreadLocalCredentialsCache() {
     104           6 :       credentials_ = std::make_shared<Credentials>(); // Creating empty credentials as default.
     105           6 :     }
     106             :     // The credentials object.
     107             :     CredentialsConstSharedPtr credentials_;
     108             :   };
     109             : 
     110           0 :   const std::string& clusterName() const { return cluster_name_; }
     111             : 
     112             :   // Handle fetch done.
     113             :   void handleFetchDone();
     114             : 
     115             :   // Set Credentials shared_ptr on all threads.
     116             :   void setCredentialsToAllThreads(CredentialsConstUniquePtr&& creds);
     117             : 
     118             :   // Returns true if http async client can be used instead of libcurl to fetch the aws credentials,
     119             :   // else false.
     120             :   bool useHttpAsyncClient();
     121             : 
     122             :   Api::Api& api_;
     123             :   // The optional server factory context.
     124             :   ServerFactoryContextOptRef context_;
     125             :   // Store the method to fetch metadata from libcurl (deprecated)
     126             :   CurlMetadataFetcher fetch_metadata_using_curl_;
     127             :   // The callback used to create a MetadataFetcher instance.
     128             :   CreateMetadataFetcherCb create_metadata_fetcher_cb_;
     129             :   // The cluster name to use for internal static cluster pointing towards the credentials provider.
     130             :   const std::string cluster_name_;
     131             :   // The cluster type to use for internal static cluster pointing towards the credentials provider.
     132             :   const envoy::config::cluster::v3::Cluster::DiscoveryType cluster_type_;
     133             :   // The uri of internal static cluster credentials provider.
     134             :   const std::string uri_;
     135             :   // The cache duration of the fetched credentials.
     136             :   const std::chrono::seconds cache_duration_;
     137             :   // The thread local slot for cache.
     138             :   ThreadLocal::TypedSlotPtr<ThreadLocalCredentialsCache> tls_;
     139             :   // The timer to trigger fetch due to cache duration.
     140             :   Envoy::Event::TimerPtr cache_duration_timer_;
     141             :   // The Metadata fetcher object.
     142             :   MetadataFetcherPtr metadata_fetcher_;
     143             :   // Callback function to call on successful metadata fetch.
     144             :   OnAsyncFetchCb on_async_fetch_cb_;
     145             :   // To determine if credentials fetching can continue even after metadata fetch failure.
     146             :   bool continue_on_async_fetch_failure_ = false;
     147             :   // Reason to log on fetch failure while continue.
     148             :   std::string continue_on_async_fetch_failure_reason_ = "";
     149             :   // Last update time to determine expiration.
     150             :   SystemTime last_updated_;
     151             :   // Cache credentials when using libcurl.
     152             :   Credentials cached_credentials_;
     153             :   // Lock guard.
     154             :   Thread::MutexBasicLockable lock_;
     155             :   // The init target.
     156             :   std::unique_ptr<Init::TargetImpl> init_target_;
     157             :   // Used in logs.
     158             :   const std::string debug_name_;
     159             : };
     160             : 
     161             : /**
     162             :  * Retrieve AWS credentials from the instance metadata.
     163             :  *
     164             :  * https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials
     165             :  */
     166             : class InstanceProfileCredentialsProvider : public MetadataCredentialsProviderBase,
     167             :                                            public MetadataFetcher::MetadataReceiver {
     168             : public:
     169             :   InstanceProfileCredentialsProvider(Api::Api& api, ServerFactoryContextOptRef context,
     170             :                                      const CurlMetadataFetcher& fetch_metadata_using_curl,
     171             :                                      CreateMetadataFetcherCb create_metadata_fetcher_cb,
     172             :                                      absl::string_view cluster_name);
     173             : 
     174             :   // Following functions are for MetadataFetcher::MetadataReceiver interface
     175             :   void onMetadataSuccess(const std::string&& body) override;
     176             :   void onMetadataError(Failure reason) override;
     177             : 
     178             : private:
     179             :   bool needsRefresh() override;
     180             :   void refresh() override;
     181             :   void fetchInstanceRole(const std::string&& token, bool async = false);
     182           0 :   void fetchInstanceRoleAsync(const std::string&& token) {
     183           0 :     fetchInstanceRole(std::move(token), true);
     184           0 :   }
     185             :   void fetchCredentialFromInstanceRole(const std::string&& instance_role, const std::string&& token,
     186             :                                        bool async = false);
     187             :   void fetchCredentialFromInstanceRoleAsync(const std::string&& instance_role,
     188           0 :                                             const std::string&& token) {
     189           0 :     fetchCredentialFromInstanceRole(std::move(instance_role), std::move(token), true);
     190           0 :   }
     191             :   void extractCredentials(const std::string&& credential_document_value, bool async = false);
     192           0 :   void extractCredentialsAsync(const std::string&& credential_document_value) {
     193           0 :     extractCredentials(std::move(credential_document_value), true);
     194           0 :   }
     195             : };
     196             : 
     197             : /**
     198             :  * Retrieve AWS credentials from the task metadata.
     199             :  *
     200             :  * https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html#enable_task_iam_roles
     201             :  */
     202             : class TaskRoleCredentialsProvider : public MetadataCredentialsProviderBase,
     203             :                                     public MetadataFetcher::MetadataReceiver {
     204             : public:
     205             :   TaskRoleCredentialsProvider(Api::Api& api, ServerFactoryContextOptRef context,
     206             :                               const CurlMetadataFetcher& fetch_metadata_using_curl,
     207             :                               CreateMetadataFetcherCb create_metadata_fetcher_cb,
     208             :                               absl::string_view credential_uri,
     209             :                               absl::string_view authorization_token,
     210             :                               absl::string_view cluster_name);
     211             : 
     212             :   // Following functions are for MetadataFetcher::MetadataReceiver interface
     213             :   void onMetadataSuccess(const std::string&& body) override;
     214             :   void onMetadataError(Failure reason) override;
     215             : 
     216             : private:
     217             :   SystemTime expiration_time_;
     218             :   const std::string credential_uri_;
     219             :   const std::string authorization_token_;
     220             : 
     221             :   bool needsRefresh() override;
     222             :   void refresh() override;
     223             :   void extractCredentials(const std::string&& credential_document_value);
     224             : };
     225             : 
     226             : /**
     227             :  * Retrieve AWS credentials from Security Token Service using a web identity token (e.g. OAuth,
     228             :  * OpenID)
     229             :  */
     230             : class WebIdentityCredentialsProvider : public MetadataCredentialsProviderBase,
     231             :                                        public MetadataFetcher::MetadataReceiver {
     232             : public:
     233             :   WebIdentityCredentialsProvider(Api::Api& api, ServerFactoryContextOptRef context,
     234             :                                  const CurlMetadataFetcher& fetch_metadata_using_curl,
     235             :                                  CreateMetadataFetcherCb create_metadata_fetcher_cb,
     236             :                                  absl::string_view token_file_path, absl::string_view sts_endpoint,
     237             :                                  absl::string_view role_arn, absl::string_view role_session_name,
     238             :                                  absl::string_view cluster_name);
     239             : 
     240             :   // Following functions are for MetadataFetcher::MetadataReceiver interface
     241             :   void onMetadataSuccess(const std::string&& body) override;
     242             :   void onMetadataError(Failure reason) override;
     243             : 
     244             : private:
     245             :   SystemTime expiration_time_;
     246             :   const std::string token_file_path_;
     247             :   const std::string sts_endpoint_;
     248             :   const std::string role_arn_;
     249             :   const std::string role_session_name_;
     250             : 
     251             :   bool needsRefresh() override;
     252             :   void refresh() override;
     253             :   void extractCredentials(const std::string&& credential_document_value);
     254             : };
     255             : 
     256             : /**
     257             :  * AWS credentials provider chain, able to fallback between multiple credential providers.
     258             :  */
     259             : class CredentialsProviderChain : public CredentialsProvider,
     260             :                                  public Logger::Loggable<Logger::Id::aws> {
     261             : public:
     262           6 :   ~CredentialsProviderChain() override = default;
     263             : 
     264          18 :   void add(const CredentialsProviderSharedPtr& credentials_provider) {
     265          18 :     providers_.emplace_back(credentials_provider);
     266          18 :   }
     267             : 
     268             :   Credentials getCredentials() override;
     269             : 
     270             : protected:
     271             :   std::list<CredentialsProviderSharedPtr> providers_;
     272             : };
     273             : 
     274             : class CredentialsProviderChainFactories {
     275             : public:
     276           6 :   virtual ~CredentialsProviderChainFactories() = default;
     277             : 
     278             :   virtual CredentialsProviderSharedPtr createEnvironmentCredentialsProvider() const PURE;
     279             : 
     280             :   virtual CredentialsProviderSharedPtr
     281             :   createCredentialsFileCredentialsProvider(Api::Api& api) const PURE;
     282             : 
     283             :   virtual CredentialsProviderSharedPtr createWebIdentityCredentialsProvider(
     284             :       Api::Api& api, ServerFactoryContextOptRef context,
     285             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl,
     286             :       CreateMetadataFetcherCb create_metadata_fetcher_cb, absl::string_view cluster_name,
     287             :       absl::string_view token_file_path, absl::string_view sts_endpoint, absl::string_view role_arn,
     288             :       absl::string_view role_session_name) const PURE;
     289             : 
     290             :   virtual CredentialsProviderSharedPtr createTaskRoleCredentialsProvider(
     291             :       Api::Api& api, ServerFactoryContextOptRef context,
     292             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl,
     293             :       CreateMetadataFetcherCb create_metadata_fetcher_cb, absl::string_view cluster_name,
     294             :       absl::string_view credential_uri, absl::string_view authorization_token = {}) const PURE;
     295             : 
     296             :   virtual CredentialsProviderSharedPtr createInstanceProfileCredentialsProvider(
     297             :       Api::Api& api, ServerFactoryContextOptRef context,
     298             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl,
     299             :       CreateMetadataFetcherCb create_metadata_fetcher_cb,
     300             :       absl::string_view cluster_name) const PURE;
     301             : };
     302             : 
     303             : /**
     304             :  * Default AWS credentials provider chain.
     305             :  *
     306             :  * Reference implementation:
     307             :  * https://github.com/aws/aws-sdk-cpp/blob/master/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp#L44
     308             :  */
     309             : class DefaultCredentialsProviderChain : public CredentialsProviderChain,
     310             :                                         public CredentialsProviderChainFactories {
     311             : public:
     312             :   DefaultCredentialsProviderChain(
     313             :       Api::Api& api, ServerFactoryContextOptRef context, absl::string_view region,
     314             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl)
     315           6 :       : DefaultCredentialsProviderChain(api, context, region, fetch_metadata_using_curl, *this) {}
     316             : 
     317             :   DefaultCredentialsProviderChain(
     318             :       Api::Api& api, ServerFactoryContextOptRef context, absl::string_view region,
     319             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl,
     320             :       const CredentialsProviderChainFactories& factories);
     321             : 
     322             : private:
     323           6 :   CredentialsProviderSharedPtr createEnvironmentCredentialsProvider() const override {
     324           6 :     return std::make_shared<EnvironmentCredentialsProvider>();
     325           6 :   }
     326             : 
     327             :   CredentialsProviderSharedPtr
     328           6 :   createCredentialsFileCredentialsProvider(Api::Api& api) const override {
     329           6 :     return std::make_shared<CredentialsFileCredentialsProvider>(api);
     330           6 :   }
     331             : 
     332             :   CredentialsProviderSharedPtr createTaskRoleCredentialsProvider(
     333             :       Api::Api& api, ServerFactoryContextOptRef context,
     334             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl,
     335             :       CreateMetadataFetcherCb create_metadata_fetcher_cb, absl::string_view cluster_name,
     336           0 :       absl::string_view credential_uri, absl::string_view authorization_token = {}) const override {
     337           0 :     return std::make_shared<TaskRoleCredentialsProvider>(api, context, fetch_metadata_using_curl,
     338           0 :                                                          create_metadata_fetcher_cb, credential_uri,
     339           0 :                                                          authorization_token, cluster_name);
     340           0 :   }
     341             : 
     342             :   CredentialsProviderSharedPtr createInstanceProfileCredentialsProvider(
     343             :       Api::Api& api, ServerFactoryContextOptRef context,
     344             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl,
     345             :       CreateMetadataFetcherCb create_metadata_fetcher_cb,
     346           6 :       absl::string_view cluster_name) const override {
     347           6 :     return std::make_shared<InstanceProfileCredentialsProvider>(
     348           6 :         api, context, fetch_metadata_using_curl, create_metadata_fetcher_cb, cluster_name);
     349           6 :   }
     350             : 
     351             :   CredentialsProviderSharedPtr createWebIdentityCredentialsProvider(
     352             :       Api::Api& api, ServerFactoryContextOptRef context,
     353             :       const MetadataCredentialsProviderBase::CurlMetadataFetcher& fetch_metadata_using_curl,
     354             :       CreateMetadataFetcherCb create_metadata_fetcher_cb, absl::string_view cluster_name,
     355             :       absl::string_view token_file_path, absl::string_view sts_endpoint, absl::string_view role_arn,
     356           0 :       absl::string_view role_session_name) const override {
     357           0 :     return std::make_shared<WebIdentityCredentialsProvider>(
     358           0 :         api, context, fetch_metadata_using_curl, create_metadata_fetcher_cb, token_file_path,
     359           0 :         sts_endpoint, role_arn, role_session_name, cluster_name);
     360           0 :   }
     361             : };
     362             : 
     363             : using InstanceProfileCredentialsProviderPtr = std::shared_ptr<InstanceProfileCredentialsProvider>;
     364             : using TaskRoleCredentialsProviderPtr = std::shared_ptr<TaskRoleCredentialsProvider>;
     365             : using WebIdentityCredentialsProviderPtr = std::shared_ptr<WebIdentityCredentialsProvider>;
     366             : 
     367             : } // namespace Aws
     368             : } // namespace Common
     369             : } // namespace Extensions
     370             : } // namespace Envoy

Generated by: LCOV version 1.15