Skip to content

Commit

Permalink
Adds support for Anonymous Credentials (#171)
Browse files Browse the repository at this point in the history
  • Loading branch information
waahm7 committed Aug 15, 2022
1 parent 59556cd commit 831fa58
Show file tree
Hide file tree
Showing 8 changed files with 278 additions and 10 deletions.
35 changes: 35 additions & 0 deletions include/aws/auth/credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,17 @@ struct aws_credentials *aws_credentials_new(
struct aws_byte_cursor session_token_cursor,
uint64_t expiration_timepoint_seconds);

/**
* Creates a new set of aws anonymous credentials.
* Use Anonymous credentials, when you want to skip the signing process.
*
* @param allocator memory allocator to use
*
* @return a valid credentials object, or NULL
*/
AWS_AUTH_API
struct aws_credentials *aws_credentials_new_anonymous(struct aws_allocator *allocator);

/**
* Creates a new set of AWS credentials
*
Expand Down Expand Up @@ -570,6 +581,16 @@ uint64_t aws_credentials_get_expiration_timepoint_seconds(const struct aws_crede
AWS_AUTH_API
struct aws_ecc_key_pair *aws_credentials_get_ecc_key_pair(const struct aws_credentials *credentials);

/**
* If credentials are anonymous, then the signing process is skipped.
*
* @param credentials credentials to check
*
* @return true if the credentials are anonymous; false otherwise.
*/
AWS_AUTH_API
bool aws_credentials_is_anonymous(const struct aws_credentials *credentials);

/*
* Credentials provider APIs
*/
Expand Down Expand Up @@ -624,6 +645,20 @@ struct aws_credentials_provider *aws_credentials_provider_new_static(
struct aws_allocator *allocator,
const struct aws_credentials_provider_static_options *options);

/**
* Creates a simple anonymous credentials provider
*
* @param allocator memory allocator to use for all memory allocation
* @param shutdown_options an optional shutdown callback that gets
* invoked when the resources used by the provider are no longer in use.
*
* @return the newly-constructed credentials provider, or NULL if an error occurred.
*/
AWS_AUTH_API
struct aws_credentials_provider *aws_credentials_provider_new_anonymous(
struct aws_allocator *allocator,
const struct aws_credentials_provider_shutdown_options *shutdown_options);

/**
* Creates a provider that returns credentials sourced from the environment variables:
*
Expand Down
37 changes: 31 additions & 6 deletions source/credentials.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ struct aws_credentials *aws_credentials_new(
return NULL;
}

struct aws_credentials *aws_credentials_new_anonymous(struct aws_allocator *allocator) {

struct aws_credentials *credentials = aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials));

credentials->allocator = allocator;
aws_atomic_init_int(&credentials->ref_count, 1);

credentials->expiration_timepoint_seconds = UINT64_MAX;

return credentials;
}

static void s_aws_credentials_destroy(struct aws_credentials *credentials) {
if (credentials == NULL) {
return;
Expand Down Expand Up @@ -156,25 +168,33 @@ void aws_credentials_release(const struct aws_credentials *credentials) {
}
}

static struct aws_byte_cursor s_empty_token_cursor = {
.ptr = NULL,
.len = 0,
};

struct aws_byte_cursor aws_credentials_get_access_key_id(const struct aws_credentials *credentials) {
if (credentials->access_key_id == NULL) {
return s_empty_token_cursor;
}

return aws_byte_cursor_from_string(credentials->access_key_id);
}

struct aws_byte_cursor aws_credentials_get_secret_access_key(const struct aws_credentials *credentials) {
if (credentials->secret_access_key == NULL) {
return s_empty_token_cursor;
}

return aws_byte_cursor_from_string(credentials->secret_access_key);
}

static struct aws_byte_cursor s_empty_session_token_cursor = {
.ptr = NULL,
.len = 0,
};

struct aws_byte_cursor aws_credentials_get_session_token(const struct aws_credentials *credentials) {
if (credentials->session_token != NULL) {
return aws_byte_cursor_from_string(credentials->session_token);
}

return s_empty_session_token_cursor;
return s_empty_token_cursor;
}

uint64_t aws_credentials_get_expiration_timepoint_seconds(const struct aws_credentials *credentials) {
Expand All @@ -185,6 +205,11 @@ struct aws_ecc_key_pair *aws_credentials_get_ecc_key_pair(const struct aws_crede
return credentials->ecc_key;
}

bool aws_credentials_is_anonymous(const struct aws_credentials *credentials) {
AWS_PRECONDITION(credentials);
return credentials->access_key_id == NULL && credentials->secret_access_key == NULL;
}

struct aws_credentials *aws_credentials_new_from_string(
struct aws_allocator *allocator,
const struct aws_string *access_key_id,
Expand Down
60 changes: 60 additions & 0 deletions source/credentials_provider_anonymous.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

#include <aws/auth/credentials.h>
#include <aws/auth/private/credentials_utils.h>

static int s_anonymous_credentials_provider_get_credentials_async(
struct aws_credentials_provider *provider,
aws_on_get_credentials_callback_fn callback,
void *user_data) {

struct aws_credentials *credentials = provider->impl;

AWS_LOGF_INFO(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
"(id=%p) Anonymous credentials provider successfully sourced credentials",
(void *)provider);
callback(credentials, AWS_ERROR_SUCCESS, user_data);

return AWS_OP_SUCCESS;
}

static void s_anonymous_credentials_provider_destroy(struct aws_credentials_provider *provider) {
struct aws_credentials *credentials = provider->impl;

aws_credentials_release(credentials);
aws_credentials_provider_invoke_shutdown_callback(provider);
aws_mem_release(provider->allocator, provider);
}

static struct aws_credentials_provider_vtable s_aws_credentials_provider_anonymous_vtable = {
.get_credentials = s_anonymous_credentials_provider_get_credentials_async,
.destroy = s_anonymous_credentials_provider_destroy,
};

struct aws_credentials_provider *aws_credentials_provider_new_anonymous(
struct aws_allocator *allocator,
const struct aws_credentials_provider_shutdown_options *shutdown_options) {

struct aws_credentials_provider *provider = aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider));

struct aws_credentials *credentials = aws_credentials_new_anonymous(allocator);
if (credentials == NULL) {
goto on_new_credentials_failure;
}

aws_credentials_provider_init_base(provider, allocator, &s_aws_credentials_provider_anonymous_vtable, credentials);

provider->shutdown_options = *shutdown_options;

return provider;

on_new_credentials_failure:

aws_mem_release(allocator, provider);

return NULL;
}
12 changes: 10 additions & 2 deletions source/signing.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ static void s_perform_signing(struct aws_signing_state_aws *state) {
goto done;
}

if (aws_credentials_is_anonymous(state->config.credentials)) {
result = &state->result;
goto done;
}

if (aws_signing_build_canonical_request(state)) {
state->error_code = s_aws_last_error_or_unknown();
AWS_LOGF_ERROR(
Expand Down Expand Up @@ -103,7 +108,9 @@ static void s_aws_signing_on_get_credentials(struct aws_credentials *credentials

state->error_code = AWS_AUTH_SIGNING_NO_CREDENTIALS;
} else {
if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC) {
if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC &&
!aws_credentials_is_anonymous(credentials)) {

state->config.credentials = aws_credentials_new_ecc_from_aws_credentials(state->allocator, credentials);
if (state->config.credentials == NULL) {
state->error_code = AWS_AUTH_SIGNING_NO_CREDENTIALS;
Expand Down Expand Up @@ -139,7 +146,8 @@ int aws_sign_request_aws(
}

if (signing_state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC) {
if (signing_state->config.credentials != NULL) {
if (signing_state->config.credentials != NULL &&
!aws_credentials_is_anonymous(signing_state->config.credentials)) {
/*
* If these are regular credentials, try to derive ecc-based ones
*/
Expand Down
2 changes: 1 addition & 1 deletion source/signing_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ int aws_validate_aws_signing_config_aws(const struct aws_signing_config_aws *con
return aws_raise_error(AWS_AUTH_SIGNING_INVALID_CONFIGURATION);
}

if (config->credentials != NULL) {
if (config->credentials != NULL && !aws_credentials_is_anonymous(config->credentials)) {
if (aws_credentials_get_access_key_id(config->credentials).len == 0 ||
aws_credentials_get_secret_access_key(config->credentials).len == 0) {
AWS_LOGF_ERROR(
Expand Down
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ file(GLOB TEST_HDRS "*.h")
file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC})

add_test_case(credentials_create_destroy_test)
add_test_case(anonymous_credentials_create_destroy_test)
add_test_case(static_credentials_provider_basic_test)
add_test_case(anonymous_credentials_provider_basic_test)
add_test_case(environment_credentials_provider_basic_test)
add_test_case(environment_credentials_provider_negative_test)
add_test_case(cached_credentials_provider_elapsed_test)
Expand Down Expand Up @@ -127,6 +129,8 @@ add_test_case(sigv4_fail_credential_param_test)
add_test_case(sigv4_fail_algorithm_param_test)
add_test_case(sigv4_fail_signed_headers_param_test)
add_test_case(signer_null_credentials_test)
add_test_case(signer_anonymous_credentials_test)
add_test_case(signer_anonymous_credentials_provider_test)
add_test_case(sigv4_chunked_signing_test)
add_test_case(sigv4a_chunked_signing_test)
add_test_case(sigv4_trailing_headers_signing_test)
Expand Down
44 changes: 43 additions & 1 deletion tests/credentials_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ static int s_credentials_create_destroy_test(struct aws_allocator *allocator, vo

AWS_TEST_CASE(credentials_create_destroy_test, s_credentials_create_destroy_test);

static int s_anonymous_credentials_create_destroy_test(struct aws_allocator *allocator, void *ctx) {
(void)ctx;

struct aws_credentials *credentials = aws_credentials_new_anonymous(allocator);

ASSERT_NOT_NULL(credentials);
ASSERT_TRUE(aws_credentials_is_anonymous(credentials));
ASSERT_NULL(aws_credentials_get_access_key_id(credentials).ptr);
ASSERT_NULL(aws_credentials_get_secret_access_key(credentials).ptr);
ASSERT_NULL(aws_credentials_get_session_token(credentials).ptr);

aws_credentials_release(credentials);
return 0;
}

AWS_TEST_CASE(anonymous_credentials_create_destroy_test, s_anonymous_credentials_create_destroy_test);

struct aws_credentials_shutdown_checker {
struct aws_mutex lock;
struct aws_condition_variable signal;
Expand Down Expand Up @@ -111,7 +128,7 @@ static int s_do_basic_provider_test(

ASSERT_TRUE(callback_results.count == expected_calls);

if (callback_results.credentials != NULL) {
if (callback_results.credentials != NULL && !aws_credentials_is_anonymous(callback_results.credentials)) {
ASSERT_CURSOR_VALUE_STRING_EQUALS(
aws_credentials_get_access_key_id(callback_results.credentials), expected_access_key_id);

Expand Down Expand Up @@ -169,6 +186,31 @@ static int s_static_credentials_provider_basic_test(struct aws_allocator *alloca

AWS_TEST_CASE(static_credentials_provider_basic_test, s_static_credentials_provider_basic_test);

static int s_anonymous_credentials_provider_basic_test(struct aws_allocator *allocator, void *ctx) {
(void)ctx;

struct aws_credentials_provider_shutdown_options shutdown_options = {
.shutdown_callback = s_on_shutdown_complete,
.shutdown_user_data = NULL,
};

s_aws_credentials_shutdown_checker_init();

struct aws_credentials_provider *provider = aws_credentials_provider_new_anonymous(allocator, &shutdown_options);

ASSERT_TRUE(s_do_basic_provider_test(provider, 1, NULL, NULL, NULL) == AWS_OP_SUCCESS);

aws_credentials_provider_release(provider);

s_aws_wait_for_provider_shutdown_callback();

s_aws_credentials_shutdown_checker_clean_up();

return 0;
}

AWS_TEST_CASE(anonymous_credentials_provider_basic_test, s_anonymous_credentials_provider_basic_test);

static int s_environment_credentials_provider_basic_test(struct aws_allocator *allocator, void *ctx) {
(void)ctx;

Expand Down
Loading

0 comments on commit 831fa58

Please sign in to comment.