1
#pragma once
2

            
3
#include "source/common/common/cancel_wrapper.h"
4
#include "source/extensions/common/aws/aws_cluster_manager.h"
5
#include "source/extensions/common/aws/credentials_provider.h"
6
#include "source/extensions/common/aws/metadata_fetcher.h"
7

            
8
namespace Envoy {
9
namespace Extensions {
10
namespace Common {
11
namespace Aws {
12

            
13
constexpr char EXPIRATION_FORMAT[] = "%E4Y-%m-%dT%H:%M:%S%z";
14

            
15
#define ALL_METADATACREDENTIALSPROVIDER_STATS(COUNTER, GAUGE)                                      \
16
197
  COUNTER(credential_refreshes_performed)                                                          \
17
197
  COUNTER(credential_refreshes_failed)                                                             \
18
197
  COUNTER(credential_refreshes_succeeded)                                                          \
19
197
  GAUGE(metadata_refresh_state, Accumulate)
20

            
21
struct MetadataCredentialsProviderStats {
22
  ALL_METADATACREDENTIALSPROVIDER_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT)
23
};
24

            
25
/**
26
 *  CreateMetadataFetcherCb is a callback interface for creating a MetadataFetcher instance.
27
 */
28
using CreateMetadataFetcherCb =
29
    std::function<MetadataFetcherPtr(Upstream::ClusterManager&, absl::string_view)>;
30

            
31
class MetadataCredentialsProviderBase
32
    : public CredentialsProvider,
33
      public Logger::Loggable<Logger::Id::aws>,
34
      public AwsManagedClusterUpdateCallbacks,
35
      public std::enable_shared_from_this<MetadataCredentialsProviderBase> {
36
public:
37
  friend class MetadataCredentialsProviderBaseFriend;
38
  using OnAsyncFetchCb = std::function<void(const std::string&&)>;
39

            
40
  MetadataCredentialsProviderBase(Server::Configuration::ServerFactoryContext& context,
41
                                  AwsClusterManagerPtr aws_cluster_manager,
42
                                  absl::string_view cluster_name,
43
                                  CreateMetadataFetcherCb create_metadata_fetcher_cb,
44
                                  MetadataFetcher::MetadataReceiver::RefreshState refresh_state,
45
                                  std::chrono::seconds initialization_timer);
46

            
47
  ~MetadataCredentialsProviderBase() override;
48

            
49
  Credentials getCredentials() override;
50
  bool credentialsPending() override;
51

            
52
  // Get the Metadata credentials cache duration.
53
  std::chrono::seconds getCacheDuration();
54

            
55
  // Store the RAII cluster callback handle following registration call with AWS cluster manager
56
100
  void setClusterReadyCallbackHandle(AwsManagedClusterUpdateCallbacksHandlePtr handle) {
57
100
    callback_handle_ = std::move(handle);
58
100
  }
59

            
60
  CredentialSubscriberCallbacksHandlePtr
61
  subscribeToCredentialUpdates(CredentialSubscriberCallbacksSharedPtr cs);
62

            
63
protected:
64
  struct ThreadLocalCredentialsCache : public ThreadLocal::ThreadLocalObject {
65
239
    ThreadLocalCredentialsCache() : credentials_(std::make_shared<Credentials>()) {};
66

            
67
    // The credentials object.
68
    CredentialsConstSharedPtr credentials_;
69
    // Lock guard.
70
    Thread::MutexBasicLockable lock_;
71
  };
72

            
73
  // Set anonymous credentials to all threads, update stats and close async
74
  void credentialsRetrievalError();
75

            
76
99
  const std::string& clusterName() const { return cluster_name_; }
77

            
78
  // Callback from AWS cluster manager, triggered when our cluster comes online
79
  void onClusterAddOrUpdate() override;
80

            
81
  // Handle fetch done.
82
  void handleFetchDone();
83

            
84
  // Set Credentials shared_ptr on all threads.
85
  void setCredentialsToAllThreads(CredentialsConstUniquePtr&& creds);
86

            
87
  virtual void refresh() PURE;
88

            
89
  Server::Configuration::ServerFactoryContext& context_;
90
  // The callback used to create a MetadataFetcher instance.
91
  CreateMetadataFetcherCb create_metadata_fetcher_cb_;
92
  // The cluster name to use for internal static cluster pointing towards the credentials provider.
93
  std::string cluster_name_;
94
  // The cache duration of the fetched credentials.
95
  std::chrono::seconds cache_duration_;
96
  // Metadata receiver state, describing where we are along the initial credential refresh process
97
  MetadataFetcher::MetadataReceiver::RefreshState refresh_state_;
98
  // Metadata receiver initialization timer - number of seconds between retries during the first
99
  // credential retrieval process
100
  std::chrono::seconds initialization_timer_;
101
  // The timer to trigger fetch due to cache duration.
102
  Envoy::Event::TimerPtr cache_duration_timer_;
103
  // The Metadata fetcher object.
104
  MetadataFetcherPtr metadata_fetcher_;
105
  // Callback function to call on successful metadata fetch.
106
  OnAsyncFetchCb on_async_fetch_cb_;
107
  // To determine if credentials fetching can continue even after metadata fetch failure.
108
  bool continue_on_async_fetch_failure_ = false;
109
  // Reason to log on fetch failure while continue.
110
  std::string continue_on_async_fetch_failure_reason_ = "";
111
  // Last update time to determine expiration.
112
  SystemTime last_updated_;
113
  // The expiration time received in any returned token
114
  absl::optional<SystemTime> expiration_time_;
115
  // Tls slot
116
  ThreadLocal::TypedSlotPtr<ThreadLocalCredentialsCache> tls_slot_ = nullptr;
117
  // Stats scope
118
  Stats::ScopeSharedPtr scope_ = nullptr;
119
  // Pointer to our stats structure
120
  std::shared_ptr<MetadataCredentialsProviderStats> stats_;
121
  // AWS Cluster Manager for creating clusters and retrieving URIs when async fetch is needed
122
  AwsClusterManagerPtr aws_cluster_manager_;
123
  // RAII handle for callbacks from AWS cluster manager
124
  AwsManagedClusterUpdateCallbacksHandlePtr callback_handle_;
125
  // Are credentials pending?
126
  std::atomic<bool> credentials_pending_ = true;
127
  Thread::MutexBasicLockable mu_;
128
  std::list<std::weak_ptr<CredentialSubscriberCallbacks>>
129
      credentials_subscribers_ ABSL_GUARDED_BY(mu_);
130
106
  CancelWrapper::CancelFunction cancel_credentials_update_callback_ = []() {};
131
};
132

            
133
} // namespace Aws
134
} // namespace Common
135
} // namespace Extensions
136
} // namespace Envoy