Skip to content

Commit 2d7a109

Browse files
authored
Customer Credential provider (aws#221)
* Customer Credential provider
1 parent 1e3f765 commit 2d7a109

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

include/aws/crt/auth/Credentials.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ namespace Aws
9292
*/
9393
using OnCredentialsResolved = std::function<void(std::shared_ptr<Credentials>, int errorCode)>;
9494

95+
/**
96+
* Invoked when the native delegate credentials provider needs to fetch a credential.
97+
*/
98+
using GetCredentialsHandler = std::function<std::shared_ptr<Credentials>()>;
99+
95100
/**
96101
* Base interface for all credentials providers. Credentials providers are objects that
97102
* retrieve AWS credentials from some source.
@@ -281,6 +286,15 @@ namespace Aws
281286
Optional<Http::HttpClientConnectionProxyOptions> ProxyOptions;
282287
};
283288

289+
/**
290+
* Configuration options for the delegate credentials provider
291+
*/
292+
struct AWS_CRT_CPP_API CredentialsProviderDelegateConfig
293+
{
294+
/* handler to provider credentials */
295+
GetCredentialsHandler Handler;
296+
};
297+
284298
/**
285299
* Simple credentials provider implementation that wraps one of the internal C-based implementations.
286300
*
@@ -381,6 +395,14 @@ namespace Aws
381395
const CredentialsProviderX509Config &config,
382396
Allocator *allocator = g_allocator);
383397

398+
/**
399+
* Creates a provider that sources credentials from the provided function.
400+
*
401+
*/
402+
static std::shared_ptr<ICredentialsProvider> CreateCredentialsProviderDelegate(
403+
const CredentialsProviderDelegateConfig &config,
404+
Allocator *allocator = g_allocator);
405+
384406
private:
385407
static void s_onCredentialsResolved(aws_credentials *credentials, int error_code, void *user_data);
386408

source/auth/Credentials.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,52 @@ namespace Aws
310310
return s_CreateWrappedProvider(aws_credentials_provider_new_x509(allocator, &raw_config), allocator);
311311
}
312312

313+
struct DelegateCredentialsProviderCallbackArgs
314+
{
315+
DelegateCredentialsProviderCallbackArgs() = default;
316+
317+
Allocator *allocator;
318+
GetCredentialsHandler m_Handler;
319+
};
320+
321+
static int s_onDelegateGetCredentials(
322+
void *delegate_user_data,
323+
aws_on_get_credentials_callback_fn callback,
324+
void *callback_user_data)
325+
{
326+
auto args = static_cast<DelegateCredentialsProviderCallbackArgs *>(delegate_user_data);
327+
auto creds = args->m_Handler();
328+
struct aws_credentials *m_credentials = (struct aws_credentials *)(void *)creds->GetUnderlyingHandle();
329+
callback(m_credentials, AWS_ERROR_SUCCESS, callback_user_data);
330+
return AWS_OP_SUCCESS;
331+
}
332+
333+
static void s_onDelegateShutdownComplete(void *user_data)
334+
{
335+
auto args = static_cast<DelegateCredentialsProviderCallbackArgs *>(user_data);
336+
Aws::Crt::Delete(args, args->allocator);
337+
}
338+
339+
std::shared_ptr<ICredentialsProvider> CredentialsProvider::CreateCredentialsProviderDelegate(
340+
const CredentialsProviderDelegateConfig &config,
341+
Allocator *allocator)
342+
{
343+
struct aws_credentials_provider_delegate_options raw_config;
344+
AWS_ZERO_STRUCT(raw_config);
345+
346+
auto delegateCallbackArgs = Aws::Crt::New<DelegateCredentialsProviderCallbackArgs>(allocator);
347+
delegateCallbackArgs->allocator = allocator;
348+
delegateCallbackArgs->m_Handler = config.Handler;
349+
raw_config.delegate_user_data = delegateCallbackArgs;
350+
raw_config.get_credentials = s_onDelegateGetCredentials;
351+
aws_credentials_provider_shutdown_options options;
352+
options.shutdown_callback = s_onDelegateShutdownComplete;
353+
options.shutdown_user_data = delegateCallbackArgs;
354+
raw_config.shutdown_options = options;
355+
return s_CreateWrappedProvider(
356+
aws_credentials_provider_new_delegate(allocator, &raw_config), allocator);
357+
}
358+
313359
} // namespace Auth
314360
} // namespace Crt
315361
} // namespace Aws

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ add_test_case(TestProviderEnvironmentGet)
4646
add_test_case(TestProviderProfileGet)
4747
add_test_case(TestProviderImdsGet)
4848
add_test_case(TestProviderDefaultChainGet)
49+
add_test_case(TestProviderDelegateGet)
4950
add_test_case(HttpRequestTestCreateDestroy)
5051
add_test_case(Sigv4SigningTestCreateDestroy)
5152
add_test_case(Sigv4SigningTestSimple)

tests/CredentialsTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,39 @@ static int s_TestProviderDefaultChainGet(struct aws_allocator *allocator, void *
232232
}
233233

234234
AWS_TEST_CASE(TestProviderDefaultChainGet, s_TestProviderDefaultChainGet)
235+
236+
static int s_TestProviderDelegateGet(struct aws_allocator *allocator, void *ctx)
237+
{
238+
(void)ctx;
239+
{
240+
ApiHandle apiHandle(allocator);
241+
242+
auto delegateGetCredentials = [&allocator]() -> std::shared_ptr<Credentials> {
243+
Credentials credentials(
244+
aws_byte_cursor_from_c_str(s_access_key_id),
245+
aws_byte_cursor_from_c_str(s_secret_access_key),
246+
aws_byte_cursor_from_c_str(s_session_token),
247+
UINT32_MAX,
248+
allocator);
249+
return Aws::Crt::MakeShared<Auth::Credentials>(allocator, credentials.GetUnderlyingHandle());
250+
};
251+
252+
CredentialsProviderDelegateConfig config;
253+
config.Handler = delegateGetCredentials;
254+
auto provider = CredentialsProvider::CreateCredentialsProviderDelegate(config, allocator);
255+
GetCredentialsWaiter waiter(provider);
256+
257+
auto creds = waiter.GetCredentials();
258+
auto cursor = creds->GetAccessKeyId();
259+
// Don't use ASSERT_STR_EQUALS(), which could log actual credentials if test fails.
260+
ASSERT_TRUE(aws_byte_cursor_eq_c_str(&cursor, s_access_key_id));
261+
cursor = creds->GetSecretAccessKey();
262+
ASSERT_TRUE(aws_byte_cursor_eq_c_str(&cursor, s_secret_access_key));
263+
cursor = creds->GetSessionToken();
264+
ASSERT_TRUE(aws_byte_cursor_eq_c_str(&cursor, s_session_token));
265+
}
266+
267+
return AWS_OP_SUCCESS;
268+
}
269+
270+
AWS_TEST_CASE(TestProviderDelegateGet, s_TestProviderDelegateGet)

0 commit comments

Comments
 (0)