1
#include "source/extensions/common/aws/credential_provider_chains.h"
2

            
3
#include <memory>
4

            
5
#include "envoy/extensions/common/aws/v3/credential_provider.pb.h"
6

            
7
#include "source/extensions/common/aws/credential_providers/assume_role_credentials_provider.h"
8
#include "source/extensions/common/aws/credential_providers/container_credentials_provider.h"
9
#include "source/extensions/common/aws/credential_providers/iam_roles_anywhere_credentials_provider.h"
10
#include "source/extensions/common/aws/credential_providers/iam_roles_anywhere_x509_credentials_provider.h"
11
#include "source/extensions/common/aws/credential_providers/instance_profile_credentials_provider.h"
12
#include "source/extensions/common/aws/signers/iam_roles_anywhere_sigv4_signer_impl.h"
13
#include "source/extensions/common/aws/signers/sigv4_signer_impl.h"
14
#include "source/extensions/common/aws/utility.h"
15

            
16
#include "absl/strings/str_replace.h"
17

            
18
namespace Envoy {
19
namespace Extensions {
20
namespace Common {
21
namespace Aws {
22

            
23
SINGLETON_MANAGER_REGISTRATION(aws_cluster_manager);
24

            
25
absl::StatusOr<CredentialsProviderChainSharedPtr>
26
CommonCredentialsProviderChain::customCredentialsProviderChain(
27
    Server::Configuration::ServerFactoryContext& context, absl::string_view region,
28
16
    const envoy::extensions::common::aws::v3::AwsCredentialProvider& credential_provider_config) {
29
16
  if (credential_provider_config.custom_credential_provider_chain() &&
30
16
      !credential_provider_config.has_assume_role_credential_provider() &&
31
16
      !credential_provider_config.has_container_credential_provider() &&
32
16
      !credential_provider_config.has_credentials_file_provider() &&
33
16
      !credential_provider_config.has_environment_credential_provider() &&
34
16
      !credential_provider_config.has_iam_roles_anywhere_credential_provider() &&
35
16
      !credential_provider_config.has_inline_credential() &&
36
16
      !credential_provider_config.has_instance_profile_credential_provider() &&
37
16
      !credential_provider_config.has_assume_role_with_web_identity_provider()) {
38
2
    return absl::InvalidArgumentError(
39
2
        "Custom credential provider chain must have at least one credential provider");
40
2
  }
41

            
42
14
  auto chain =
43
14
      std::make_shared<CommonCredentialsProviderChain>(context, region, credential_provider_config);
44
14
  chain->setupSubscriptions();
45
14
  return chain;
46
16
}
47
CredentialsProviderChainSharedPtr CommonCredentialsProviderChain::defaultCredentialsProviderChain(
48
56
    Server::Configuration::ServerFactoryContext& context, absl::string_view region) {
49
56
  auto chain = std::make_shared<CommonCredentialsProviderChain>(context, region, absl::nullopt);
50
56
  chain->setupSubscriptions();
51
56
  return chain;
52
56
}
53

            
54
70
void CommonCredentialsProviderChain::setupSubscriptions() {
55
209
  for (auto& provider : providers_) {
56
    // Set up subscription for each provider that supports it
57
209
    auto metadata_provider = std::dynamic_pointer_cast<MetadataCredentialsProviderBase>(provider);
58
209
    if (metadata_provider) {
59
84
      storeSubscription(metadata_provider->subscribeToCredentialUpdates(
60
84
          std::static_pointer_cast<CredentialSubscriberCallbacks>(shared_from_this())));
61
84
    }
62
209
  }
63
70
}
64

            
65
CommonCredentialsProviderChain::CommonCredentialsProviderChain(
66
    Server::Configuration::ServerFactoryContext& context, absl::string_view region,
67
    AwsCredentialProviderOptRef credential_provider_config,
68
113
    CredentialsProviderChainFactories& factories) {
69

            
70
113
  envoy::extensions::common::aws::v3::AwsCredentialProvider chain_to_create;
71

            
72
  // If a credential provider config is provided, then we will use that as the definition of our
73
  // chain
74
113
  if (credential_provider_config.has_value() &&
75
113
      credential_provider_config->custom_credential_provider_chain()) {
76
10
    chain_to_create.CopyFrom(credential_provider_config.value());
77
10
    ENVOY_LOG(debug, "Creating custom credentials provider chain");
78
103
  } else {
79
    // No chain configuration provided, so use the following credential providers as the default:
80
    //  - Environment credentials provider
81
    //  - Credentials file provider
82
    //  - Container credentials provider
83
    //  - Instance profile credentials provider
84
    //  - Assume role with web identity provider
85
    // These credential providers can all be instantiated with no additional configuration required
86
103
    chain_to_create.mutable_environment_credential_provider();
87
103
    chain_to_create.mutable_credentials_file_provider();
88
103
    chain_to_create.mutable_container_credential_provider();
89
103
    chain_to_create.mutable_instance_profile_credential_provider();
90
103
    chain_to_create.mutable_assume_role_with_web_identity_provider();
91
103
    if (credential_provider_config.has_value()) {
92
45
      ENVOY_LOG(debug, "Creating default credentials provider chain with custom configuration");
93
      // Merge in any credential providers that have custom configuration
94
45
      if (credential_provider_config->has_assume_role_with_web_identity_provider()) {
95
7
        chain_to_create.mutable_assume_role_with_web_identity_provider()->MergeFrom(
96
7
            credential_provider_config->assume_role_with_web_identity_provider());
97
7
      }
98
45
      if (credential_provider_config->has_credentials_file_provider()) {
99
4
        chain_to_create.mutable_credentials_file_provider()->MergeFrom(
100
4
            credential_provider_config->credentials_file_provider());
101
4
      }
102
45
      if (credential_provider_config->has_iam_roles_anywhere_credential_provider()) {
103
1
        chain_to_create.mutable_iam_roles_anywhere_credential_provider()->MergeFrom(
104
1
            credential_provider_config->iam_roles_anywhere_credential_provider());
105
1
      }
106
96
    } else {
107
58
      ENVOY_LOG(debug, "Creating default credentials provider chain");
108
58
    }
109
103
  }
110

            
111
113
  aws_cluster_manager_ =
112
113
      context.singletonManager().getTyped<Envoy::Extensions::Common::Aws::AwsClusterManagerImpl>(
113
113
          SINGLETON_MANAGER_REGISTERED_NAME(aws_cluster_manager),
114
113
          [&context] {
115
100
            return std::make_shared<Envoy::Extensions::Common::Aws::AwsClusterManagerImpl>(context);
116
100
          },
117
113
          true);
118

            
119
113
  if (chain_to_create.has_environment_credential_provider()) {
120
105
    ENVOY_LOG(debug, "Using environment credentials provider");
121
105
    add(factories.createEnvironmentCredentialsProvider());
122
105
  }
123

            
124
  // Initial state for an async credential receiver
125
113
  auto refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::FirstRefresh;
126
  // Initial amount of time for async credential receivers to wait for an initial refresh to succeed
127
113
  auto initialization_timer = std::chrono::seconds(2);
128

            
129
113
  if (chain_to_create.has_credentials_file_provider()) {
130
104
    ENVOY_LOG(debug, "Using credentials file credentials provider");
131
104
    add(factories.createCredentialsFileCredentialsProvider(
132
104
        context, chain_to_create.credentials_file_provider()));
133
104
  }
134

            
135
113
  if (chain_to_create.has_assume_role_credential_provider()) {
136
3
    auto assume_role_config = chain_to_create.assume_role_credential_provider();
137

            
138
3
    const auto sts_endpoint = Utility::getSTSEndpoint(region) + ":443";
139
3
    const auto cluster_name = stsClusterName(region);
140

            
141
    // Default session name if not provided.
142
3
    if (assume_role_config.role_session_name().empty()) {
143
1
      assume_role_config.set_role_session_name(sessionName(context.api()));
144
1
    }
145

            
146
3
    ENVOY_LOG(debug,
147
3
              "Using assumerole credentials provider with STS endpoint: {} and session name: {}",
148
3
              sts_endpoint, assume_role_config.role_session_name());
149
3
    add(factories.createAssumeRoleCredentialsProvider(context, aws_cluster_manager_, region,
150
3
                                                      assume_role_config));
151
3
  }
152

            
153
113
  if (chain_to_create.has_iam_roles_anywhere_credential_provider()) {
154
2
    ENVOY_LOG(debug, "Using IAM Roles Anywhere credentials provider");
155
2
    add(factories.createIAMRolesAnywhereCredentialsProvider(
156
2
        context, aws_cluster_manager_, region,
157
2
        chain_to_create.iam_roles_anywhere_credential_provider()));
158
2
  }
159

            
160
113
  if (chain_to_create.has_assume_role_with_web_identity_provider()) {
161
105
    auto web_identity = chain_to_create.assume_role_with_web_identity_provider();
162

            
163
    // Configure defaults if nothing is set in the config
164
105
    if (!web_identity.has_web_identity_token_data_source()) {
165
98
      web_identity.mutable_web_identity_token_data_source()->set_filename(
166
98
          absl::NullSafeStringView(std::getenv(AWS_WEB_IDENTITY_TOKEN_FILE)));
167
98
    }
168

            
169
    // Ensure we always have a watched directory configured for file-based token sources. This
170
    // ensures we automatically pick up tokens replaced on the filesystem.
171
105
    if (web_identity.web_identity_token_data_source().has_filename() &&
172
105
        !web_identity.web_identity_token_data_source().has_watched_directory()) {
173
101
      auto split = context.api().fileSystem().splitPathFromFilename(
174
101
          web_identity.web_identity_token_data_source().filename());
175
101
      if (split.ok() && !split->directory_.empty()) {
176
33
        web_identity.mutable_web_identity_token_data_source()
177
33
            ->mutable_watched_directory()
178
33
            ->set_path(split->directory_);
179
33
      }
180
101
    }
181

            
182
105
    if (web_identity.role_arn().empty()) {
183
98
      web_identity.set_role_arn(absl::NullSafeStringView(std::getenv(AWS_ROLE_ARN)));
184
98
    }
185

            
186
105
    if (web_identity.role_session_name().empty()) {
187
103
      web_identity.set_role_session_name(sessionName(context.api()));
188
103
    }
189

            
190
105
    if ((!web_identity.web_identity_token_data_source().filename().empty() ||
191
105
         !web_identity.web_identity_token_data_source().inline_bytes().empty() ||
192
105
         !web_identity.web_identity_token_data_source().inline_string().empty() ||
193
105
         !web_identity.web_identity_token_data_source().environment_variable().empty()) &&
194
105
        !web_identity.role_arn().empty()) {
195

            
196
36
      const auto sts_endpoint = Utility::getSTSEndpoint(region) + ":443";
197
36
      const auto cluster_name = stsClusterName(region);
198

            
199
36
      ENVOY_LOG(
200
36
          debug,
201
36
          "Using web identity credentials provider with STS endpoint: {} and session name: {}",
202
36
          sts_endpoint, web_identity.role_session_name());
203
36
      add(factories.createWebIdentityCredentialsProvider(context, aws_cluster_manager_, region,
204
36
                                                         web_identity));
205
36
    }
206
105
  }
207

            
208
113
  if (chain_to_create.has_container_credential_provider()) {
209
104
    const auto relative_uri =
210
104
        absl::NullSafeStringView(std::getenv(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI));
211
104
    const auto full_uri = absl::NullSafeStringView(std::getenv(AWS_CONTAINER_CREDENTIALS_FULL_URI));
212

            
213
104
    if (!relative_uri.empty()) {
214
11
      const auto uri = absl::StrCat(CONTAINER_METADATA_HOST, relative_uri);
215
11
      ENVOY_LOG(debug, "Using container role credentials provider with URI: {}", uri);
216
11
      add(factories.createContainerCredentialsProvider(
217
11
          context, aws_cluster_manager_, MetadataFetcher::create, CONTAINER_METADATA_CLUSTER, uri,
218
11
          refresh_state, initialization_timer));
219
93
    } else if (!full_uri.empty()) {
220
7
      auto authorization_token =
221
7
          absl::NullSafeStringView(std::getenv(AWS_CONTAINER_AUTHORIZATION_TOKEN));
222
7
      if (!authorization_token.empty()) {
223
6
        ENVOY_LOG(debug,
224
6
                  "Using container role credentials provider with URI: "
225
6
                  "{} and authorization token",
226
6
                  full_uri);
227
6
        add(factories.createContainerCredentialsProvider(
228
6
            context, aws_cluster_manager_, MetadataFetcher::create, CONTAINER_METADATA_CLUSTER,
229
6
            full_uri, refresh_state, initialization_timer, authorization_token));
230
6
      } else {
231
1
        ENVOY_LOG(debug, "Using container role credentials provider with URI: {}", full_uri);
232
1
        add(factories.createContainerCredentialsProvider(
233
1
            context, aws_cluster_manager_, MetadataFetcher::create, CONTAINER_METADATA_CLUSTER,
234
1
            full_uri, refresh_state, initialization_timer));
235
1
      }
236
7
    }
237
104
  }
238
113
  const auto metadata_disabled = absl::NullSafeStringView(std::getenv(AWS_EC2_METADATA_DISABLED));
239

            
240
113
  if (chain_to_create.has_instance_profile_credential_provider() && metadata_disabled != "true") {
241
79
    ENVOY_LOG(debug, "Using instance profile credentials provider");
242
79
    add(factories.createInstanceProfileCredentialsProvider(
243
79
        context, aws_cluster_manager_, MetadataFetcher::create, refresh_state, initialization_timer,
244
79
        EC2_METADATA_CLUSTER));
245
79
  }
246
113
}
247

            
248
CredentialsProviderSharedPtr CommonCredentialsProviderChain::createAssumeRoleCredentialsProvider(
249
    Server::Configuration::ServerFactoryContext& context, AwsClusterManagerPtr aws_cluster_manager,
250
    absl::string_view region,
251
2
    const envoy::extensions::common::aws::v3::AssumeRoleCredentialProvider& assume_role_config) {
252

            
253
2
  const auto refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::FirstRefresh;
254
2
  const auto initialization_timer = std::chrono::seconds(2);
255

            
256
2
  auto cluster_name = stsClusterName(region);
257
2
  auto uri = Utility::getSTSEndpoint(region) + ":443";
258

            
259
2
  auto status = aws_cluster_manager->addManagedCluster(
260
2
      cluster_name, envoy::config::cluster::v3::Cluster::LOGICAL_DNS, uri);
261

            
262
2
  CredentialsProviderChainSharedPtr credentials_provider_chain;
263

            
264
2
  if (assume_role_config.has_credential_provider()) {
265
    // If a custom chain has been configured in the assume role provider, ensure we do not allow the
266
    // user to specify another assume role provider.
267

            
268
    envoy::extensions::common::aws::v3::AwsCredentialProvider credential_provider_config;
269
    credential_provider_config.CopyFrom(assume_role_config.credential_provider());
270

            
271
    if (credential_provider_config.has_assume_role_credential_provider()) {
272
      ENVOY_LOG(warn, "Multiple assume_role_credential_provider configurations are not supported. "
273
                      "Ignoring second assume_role_credential_provider.");
274
    }
275

            
276
    credential_provider_config.clear_assume_role_credential_provider();
277
    credentials_provider_chain =
278
        std::make_shared<Extensions::Common::Aws::CommonCredentialsProviderChain>(
279
            context, region, credential_provider_config);
280
2
  } else {
281
2
    credentials_provider_chain =
282
2
        std::make_shared<Extensions::Common::Aws::CommonCredentialsProviderChain>(context, region,
283
2
                                                                                  absl::nullopt);
284
2
  }
285

            
286
  // Create our own signer specifically for signing AssumeRole API call
287
2
  auto signer = std::make_unique<SigV4SignerImpl>(
288
2
      STS_SERVICE_NAME, region, credentials_provider_chain, context,
289
2
      Extensions::Common::Aws::AwsSigningHeaderMatcherVector{},
290
2
      Extensions::Common::Aws::AwsSigningHeaderMatcherVector{});
291

            
292
2
  auto credential_provider = std::make_shared<AssumeRoleCredentialsProvider>(
293
2
      context, aws_cluster_manager, cluster_name, MetadataFetcher::create, region, refresh_state,
294
2
      initialization_timer, std::move(signer), assume_role_config);
295

            
296
2
  auto handleOr = aws_cluster_manager->addManagedClusterUpdateCallbacks(
297
2
      cluster_name,
298
2
      *std::dynamic_pointer_cast<AwsManagedClusterUpdateCallbacks>(credential_provider));
299

            
300
2
  if (handleOr.ok()) {
301
2
    credential_provider->setClusterReadyCallbackHandle(std::move(handleOr.value()));
302
2
  }
303

            
304
  // Note: Subscription will be set up after construction
305
2
  return credential_provider;
306
2
};
307

            
308
SINGLETON_MANAGER_REGISTRATION(container_credentials_provider);
309
SINGLETON_MANAGER_REGISTRATION(instance_profile_credentials_provider);
310

            
311
CredentialsProviderSharedPtr CommonCredentialsProviderChain::createContainerCredentialsProvider(
312
    Server::Configuration::ServerFactoryContext& context, AwsClusterManagerPtr aws_cluster_manager,
313
    CreateMetadataFetcherCb create_metadata_fetcher_cb, absl::string_view cluster_name,
314
    absl::string_view credential_uri, MetadataFetcher::MetadataReceiver::RefreshState refresh_state,
315
15
    std::chrono::seconds initialization_timer, absl::string_view authorization_token = {}) {
316

            
317
15
  auto status = aws_cluster_manager->addManagedCluster(
318
15
      cluster_name, envoy::config::cluster::v3::Cluster::STATIC, credential_uri);
319

            
320
15
  auto credential_provider =
321
15
      context.singletonManager()
322
15
          .getTyped<Envoy::Extensions::Common::Aws::ContainerCredentialsProvider>(
323
15
              SINGLETON_MANAGER_REGISTERED_NAME(container_credentials_provider),
324
15
              [&context, &aws_cluster_manager, create_metadata_fetcher_cb, &credential_uri,
325
15
               &refresh_state, &initialization_timer, &authorization_token, &cluster_name] {
326
10
                return std::make_shared<
327
10
                    Envoy::Extensions::Common::Aws::ContainerCredentialsProvider>(
328
10
                    context, aws_cluster_manager, create_metadata_fetcher_cb, credential_uri,
329
10
                    refresh_state, initialization_timer, authorization_token, cluster_name);
330
10
              });
331

            
332
15
  auto handleOr = aws_cluster_manager->addManagedClusterUpdateCallbacks(
333
15
      cluster_name,
334
15
      *std::dynamic_pointer_cast<AwsManagedClusterUpdateCallbacks>(credential_provider));
335
15
  if (handleOr.ok()) {
336
12
    credential_provider->setClusterReadyCallbackHandle(std::move(handleOr.value()));
337
12
  }
338

            
339
  // Note: Subscription will be set up after construction
340
15
  return credential_provider;
341
15
}
342

            
343
CredentialsProviderSharedPtr
344
CommonCredentialsProviderChain::createInstanceProfileCredentialsProvider(
345
    Server::Configuration::ServerFactoryContext& context, AwsClusterManagerPtr aws_cluster_manager,
346
    CreateMetadataFetcherCb create_metadata_fetcher_cb,
347
    MetadataFetcher::MetadataReceiver::RefreshState refresh_state,
348
63
    std::chrono::seconds initialization_timer, absl::string_view cluster_name) {
349

            
350
63
  auto status = aws_cluster_manager->addManagedCluster(
351
63
      cluster_name, envoy::config::cluster::v3::Cluster::STATIC, EC2_METADATA_HOST);
352
63
  auto credential_provider =
353
63
      context.singletonManager()
354
63
          .getTyped<Envoy::Extensions::Common::Aws::InstanceProfileCredentialsProvider>(
355
63
              SINGLETON_MANAGER_REGISTERED_NAME(instance_profile_credentials_provider),
356
63
              [&context, &aws_cluster_manager, create_metadata_fetcher_cb, &refresh_state,
357
63
               &initialization_timer, &cluster_name] {
358
58
                return std::make_shared<
359
58
                    Envoy::Extensions::Common::Aws::InstanceProfileCredentialsProvider>(
360
58
                    context, aws_cluster_manager, create_metadata_fetcher_cb, refresh_state,
361
58
                    initialization_timer, cluster_name);
362
58
              });
363

            
364
63
  auto handleOr = aws_cluster_manager->addManagedClusterUpdateCallbacks(
365
63
      cluster_name,
366
63
      *std::dynamic_pointer_cast<AwsManagedClusterUpdateCallbacks>(credential_provider));
367
63
  if (handleOr.ok()) {
368

            
369
58
    credential_provider->setClusterReadyCallbackHandle(std::move(handleOr.value()));
370
58
  }
371

            
372
  // Note: Subscription will be set up after construction
373
63
  return credential_provider;
374
63
}
375

            
376
CredentialsProviderSharedPtr CommonCredentialsProviderChain::createWebIdentityCredentialsProvider(
377
    Server::Configuration::ServerFactoryContext& context, AwsClusterManagerPtr aws_cluster_manager,
378
    absl::string_view region,
379
    const envoy::extensions::common::aws::v3::AssumeRoleWithWebIdentityCredentialProvider&
380
27
        web_identity_config) {
381

            
382
27
  const auto refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::FirstRefresh;
383
27
  const auto initialization_timer = std::chrono::seconds(2);
384

            
385
27
  auto cluster_name = stsClusterName(region);
386
27
  auto uri = Utility::getSTSEndpoint(region) + ":443";
387

            
388
27
  auto status = aws_cluster_manager->addManagedCluster(
389
27
      cluster_name, envoy::config::cluster::v3::Cluster::LOGICAL_DNS, uri);
390

            
391
27
  auto credential_provider = std::make_shared<WebIdentityCredentialsProvider>(
392
27
      context, aws_cluster_manager, cluster_name, MetadataFetcher::create, refresh_state,
393
27
      initialization_timer, web_identity_config);
394
27
  auto handleOr = aws_cluster_manager->addManagedClusterUpdateCallbacks(
395
27
      cluster_name,
396
27
      *std::dynamic_pointer_cast<AwsManagedClusterUpdateCallbacks>(credential_provider));
397

            
398
27
  if (handleOr.ok()) {
399

            
400
26
    credential_provider->setClusterReadyCallbackHandle(std::move(handleOr.value()));
401
26
  }
402

            
403
  // Note: Subscription will be set up after construction
404
27
  return credential_provider;
405
27
};
406

            
407
CredentialsProviderSharedPtr
408
CommonCredentialsProviderChain::createIAMRolesAnywhereCredentialsProvider(
409
    Server::Configuration::ServerFactoryContext& context, AwsClusterManagerPtr aws_cluster_manager,
410
    absl::string_view region,
411
    const envoy::extensions::common::aws::v3::IAMRolesAnywhereCredentialProvider&
412
2
        iam_roles_anywhere_config) const {
413

            
414
2
  const auto refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::FirstRefresh;
415
2
  const auto initialization_timer = std::chrono::seconds(2);
416

            
417
2
  const auto cluster_host =
418
2
      Utility::getRolesAnywhereEndpoint(iam_roles_anywhere_config.trust_anchor_arn());
419
2
  const auto uri = cluster_host + ":443";
420

            
421
2
  const auto cluster_name = absl::StrReplaceAll(cluster_host, {{".", "_"}});
422

            
423
2
  auto status = aws_cluster_manager->addManagedCluster(
424
2
      cluster_name, envoy::config::cluster::v3::Cluster::LOGICAL_DNS, uri);
425
2
  if (!status.ok()) {
426
    ENVOY_LOG(error, "Failed to initialize AWS Cluster Manager cluster for IAM Roles Anywhere, "
427
                     "disabling this credential provider");
428
    return nullptr;
429
  }
430

            
431
2
  auto roles_anywhere_certificate_provider =
432
2
      std::make_shared<IAMRolesAnywhereX509CredentialsProvider>(
433
2
          context, iam_roles_anywhere_config.certificate(), iam_roles_anywhere_config.private_key(),
434
2
          iam_roles_anywhere_config.has_certificate_chain()
435
2
              ? makeOptRef(iam_roles_anywhere_config.certificate_chain())
436
2
              : absl::nullopt);
437
2
  status = roles_anywhere_certificate_provider->initialize();
438
2
  if (!status.ok()) {
439
    ENVOY_LOG(error, "Failed to initialize IAM Roles Anywhere X509 Credentials Provider, disabling "
440
                     "this credential provider");
441
    return nullptr;
442
  }
443

            
444
  // Create our own x509 signer just for IAM Roles Anywhere
445
2
  auto roles_anywhere_signer =
446
2
      std::make_unique<Extensions::Common::Aws::IAMRolesAnywhereSigV4Signer>(
447
2
          absl::string_view(ROLESANYWHERE_SERVICE), absl::string_view(region),
448
2
          roles_anywhere_certificate_provider, context.mainThreadDispatcher().timeSource());
449

            
450
2
  auto credential_provider = std::make_shared<IAMRolesAnywhereCredentialsProvider>(
451
2
      context, aws_cluster_manager, cluster_name, MetadataFetcher::create, region, refresh_state,
452
2
      initialization_timer, std::move(roles_anywhere_signer), iam_roles_anywhere_config);
453
2
  auto handleOr = aws_cluster_manager->addManagedClusterUpdateCallbacks(
454
2
      cluster_name,
455
2
      *std::dynamic_pointer_cast<AwsManagedClusterUpdateCallbacks>(credential_provider));
456
2
  if (handleOr.ok()) {
457

            
458
2
    credential_provider->setClusterReadyCallbackHandle(std::move(handleOr.value()));
459
2
  }
460
2
  return credential_provider;
461
2
};
462

            
463
} // namespace Aws
464
} // namespace Common
465
} // namespace Extensions
466
} // namespace Envoy