From 274a1d21330731cc51bb742794adc70ada5f4380 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Mon, 27 Jan 2025 10:56:30 -0800 Subject: [PATCH] Add Account Id to Credentials (#260) --- .github/workflows/codecov.yml | 4 +-- include/aws/auth/credentials.h | 32 ++++++++++++++++++ source/credentials.c | 44 ++++++++++++++++++++++++ source/credentials_provider_static.c | 9 +++-- tests/credentials_tests.c | 50 +++++++++++++++++++++------- 5 files changed, 123 insertions(+), 16 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 8a7b7f78..827d326c 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -4,7 +4,7 @@ on: push: env: - BUILDER_VERSION: v0.9.72 + BUILDER_VERSION: v0.9.74 BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net BUILDER_SOURCE: releases PACKAGE_NAME: aws-c-auth @@ -28,4 +28,4 @@ jobs: run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" chmod a+x builder - ./builder build -p ${{ env.PACKAGE_NAME }} --compiler=gcc-9 --cmake-extra=-DASSERT_LOCK_HELD=ON --coverage + ./builder build -p ${{ env.PACKAGE_NAME }} --compiler=gcc --cmake-extra=-DASSERT_LOCK_HELD=ON --coverage diff --git a/include/aws/auth/credentials.h b/include/aws/auth/credentials.h index cc5d5cf5..1388cb03 100644 --- a/include/aws/auth/credentials.h +++ b/include/aws/auth/credentials.h @@ -82,6 +82,7 @@ struct aws_credentials_provider_static_options { struct aws_byte_cursor access_key_id; struct aws_byte_cursor secret_access_key; struct aws_byte_cursor session_token; + struct aws_byte_cursor account_id; }; /** @@ -743,6 +744,28 @@ struct aws_credentials *aws_credentials_new( struct aws_byte_cursor session_token_cursor, uint64_t expiration_timepoint_seconds); +/** + * Creates a new set of aws credentials with account_id + * + * @param allocator memory allocator to use + * @param access_key_id_cursor value for the aws access key id field + * @param secret_access_key_cursor value for the secret access key field + * @param session_token_cursor (optional) security token associated with the credentials + * @param account_id (optional) value for the account_id field + * @param expiration_timepoint_seconds timepoint, in seconds since epoch, that the credentials will no longer + * be valid past. For credentials that do not expire, use UINT64_MAX + * + * @return a valid credentials object, or NULL + */ +AWS_AUTH_API +struct aws_credentials *aws_credentials_new_with_account_id( + struct aws_allocator *allocator, + struct aws_byte_cursor access_key_id_cursor, + struct aws_byte_cursor secret_access_key_cursor, + struct aws_byte_cursor session_token_cursor, + struct aws_byte_cursor account_id_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. @@ -848,6 +871,15 @@ struct aws_byte_cursor aws_credentials_get_secret_access_key(const struct aws_cr AWS_AUTH_API struct aws_byte_cursor aws_credentials_get_session_token(const struct aws_credentials *credentials); +/** + * Get the AWS account id from a set of credentials + * + * @param credentials to get the account id from + * @return a byte cursor to the account id or an empty byte cursor if there is no account id + */ +AWS_AUTH_API +struct aws_byte_cursor aws_credentials_get_account_id(const struct aws_credentials *credentials); + /** * Get the expiration timepoint (in seconds since epoch) associated with a set of credentials * diff --git a/source/credentials.c b/source/credentials.c index 3340663d..b4e4b731 100644 --- a/source/credentials.c +++ b/source/credentials.c @@ -22,6 +22,7 @@ struct aws_credentials_identity { struct aws_string *access_key_id; struct aws_string *secret_access_key; struct aws_string *session_token; + struct aws_string *account_id; }; /* aws_token identity contains only a token to represent token only identities like a bearer token. */ @@ -85,6 +86,7 @@ struct aws_credentials { /* * Credentials API implementations */ + struct aws_credentials *aws_credentials_new( struct aws_allocator *allocator, struct aws_byte_cursor access_key_id_cursor, @@ -92,6 +94,26 @@ struct aws_credentials *aws_credentials_new( struct aws_byte_cursor session_token_cursor, uint64_t expiration_timepoint_seconds) { + struct aws_byte_cursor account_id; + AWS_ZERO_STRUCT(account_id); + + return aws_credentials_new_with_account_id( + allocator, + access_key_id_cursor, + secret_access_key_cursor, + session_token_cursor, + account_id, + expiration_timepoint_seconds); +} + +struct aws_credentials *aws_credentials_new_with_account_id( + struct aws_allocator *allocator, + struct aws_byte_cursor access_key_id_cursor, + struct aws_byte_cursor secret_access_key_cursor, + struct aws_byte_cursor session_token_cursor, + struct aws_byte_cursor account_id_cursor, + uint64_t expiration_timepoint_seconds) { + if (access_key_id_cursor.ptr == NULL || access_key_id_cursor.len == 0) { aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); return NULL; @@ -133,6 +155,14 @@ struct aws_credentials *aws_credentials_new( } } + if (account_id_cursor.ptr != NULL && account_id_cursor.len > 0) { + credentials_identity->account_id = + aws_string_new_from_array(allocator, account_id_cursor.ptr, account_id_cursor.len); + if (credentials_identity->account_id == NULL) { + goto error; + } + } + credentials->expiration_timepoint_seconds = expiration_timepoint_seconds; return credentials; @@ -166,6 +196,7 @@ static void s_aws_credentials_destroy(struct aws_credentials *credentials) { aws_string_destroy(credentials->identity.credentials_identity.access_key_id); aws_string_destroy_secure(credentials->identity.credentials_identity.secret_access_key); aws_string_destroy_secure(credentials->identity.credentials_identity.session_token); + aws_string_destroy_secure(credentials->identity.credentials_identity.account_id); break; case ECC_IDENTITY: aws_string_destroy(credentials->identity.ecc_identity.access_key_id); @@ -255,6 +286,19 @@ struct aws_byte_cursor aws_credentials_get_session_token(const struct aws_creden return s_empty_token_cursor; } +struct aws_byte_cursor aws_credentials_get_account_id(const struct aws_credentials *credentials) { + switch (credentials->identity_type) { + case AWS_CREDENTIALS_IDENTITY: + if (credentials->identity.credentials_identity.account_id != NULL) { + return aws_byte_cursor_from_string(credentials->identity.credentials_identity.account_id); + } + break; + default: + break; + } + return s_empty_token_cursor; +} + struct aws_byte_cursor aws_credentials_get_token(const struct aws_credentials *credentials) { switch (credentials->identity_type) { case TOKEN_IDENTITY: diff --git a/source/credentials_provider_static.c b/source/credentials_provider_static.c index 55154ee3..41d678c6 100644 --- a/source/credentials_provider_static.c +++ b/source/credentials_provider_static.c @@ -51,8 +51,13 @@ struct aws_credentials_provider *aws_credentials_provider_new_static( AWS_ZERO_STRUCT(*provider); - struct aws_credentials *credentials = aws_credentials_new( - allocator, options->access_key_id, options->secret_access_key, options->session_token, UINT64_MAX); + struct aws_credentials *credentials = aws_credentials_new_with_account_id( + allocator, + options->access_key_id, + options->secret_access_key, + options->session_token, + options->account_id, + UINT64_MAX); if (credentials == NULL) { goto on_new_credentials_failure; } diff --git a/tests/credentials_tests.c b/tests/credentials_tests.c index aef69b35..fe2a6548 100644 --- a/tests/credentials_tests.c +++ b/tests/credentials_tests.c @@ -28,6 +28,7 @@ AWS_STATIC_STRING_FROM_LITERAL(s_access_key_id_test_value, "My Access Key"); AWS_STATIC_STRING_FROM_LITERAL(s_secret_access_key_test_value, "SekritKey"); AWS_STATIC_STRING_FROM_LITERAL(s_session_token_test_value, "Some Session Token"); +AWS_STATIC_STRING_FROM_LITERAL(s_account_id_test_value, "Some Account Value"); static int s_credentials_create_destroy_test(struct aws_allocator *allocator, void *ctx) { (void)ctx; @@ -115,7 +116,8 @@ static int s_do_basic_provider_test( int expected_calls, const struct aws_string *expected_access_key_id, const struct aws_string *expected_secret_access_key, - const struct aws_string *expected_session_token) { + const struct aws_string *expected_session_token, + const struct aws_string *expected_account_id) { struct aws_get_credentials_test_callback_result callback_results; aws_get_credentials_test_callback_result_init(&callback_results, expected_calls); @@ -141,6 +143,13 @@ static int s_do_basic_provider_test( } else { ASSERT_TRUE(aws_credentials_get_session_token(callback_results.credentials).len == 0); } + + if (expected_account_id != NULL) { + ASSERT_CURSOR_VALUE_STRING_EQUALS( + aws_credentials_get_account_id(callback_results.credentials), expected_account_id); + } else { + ASSERT_TRUE(aws_credentials_get_account_id(callback_results.credentials).len == 0); + } } else { ASSERT_TRUE(expected_access_key_id == NULL); ASSERT_TRUE(expected_secret_access_key == NULL); @@ -159,6 +168,7 @@ static int s_static_credentials_provider_basic_test(struct aws_allocator *alloca .access_key_id = aws_byte_cursor_from_string(s_access_key_id_test_value), .secret_access_key = aws_byte_cursor_from_string(s_secret_access_key_test_value), .session_token = aws_byte_cursor_from_string(s_session_token_test_value), + .account_id = aws_byte_cursor_from_string(s_account_id_test_value), .shutdown_options = { .shutdown_callback = s_on_shutdown_complete, @@ -172,8 +182,12 @@ static int s_static_credentials_provider_basic_test(struct aws_allocator *alloca ASSERT_TRUE( s_do_basic_provider_test( - provider, 1, s_access_key_id_test_value, s_secret_access_key_test_value, s_session_token_test_value) == - AWS_OP_SUCCESS); + provider, + 1, + s_access_key_id_test_value, + s_secret_access_key_test_value, + s_session_token_test_value, + s_account_id_test_value) == AWS_OP_SUCCESS); aws_credentials_provider_release(provider); @@ -198,7 +212,7 @@ static int s_anonymous_credentials_provider_basic_test(struct aws_allocator *all 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); + ASSERT_TRUE(s_do_basic_provider_test(provider, 1, NULL, NULL, NULL, NULL) == AWS_OP_SUCCESS); aws_credentials_provider_release(provider); @@ -236,8 +250,12 @@ static int s_environment_credentials_provider_basic_test(struct aws_allocator *a ASSERT_TRUE( s_do_basic_provider_test( - provider, 1, s_access_key_id_test_value, s_secret_access_key_test_value, s_session_token_test_value) == - AWS_OP_SUCCESS); + provider, + 1, + s_access_key_id_test_value, + s_secret_access_key_test_value, + s_session_token_test_value, + NULL) == AWS_OP_SUCCESS); aws_credentials_provider_release(provider); @@ -270,7 +288,7 @@ static int s_environment_credentials_provider_empty_env_test(struct aws_allocato struct aws_credentials_provider *provider = aws_credentials_provider_new_environment(allocator, &options); /* Instead of getting an empty credentials, should just fail to fetch credentials */ - ASSERT_TRUE(s_do_basic_provider_test(provider, 1, NULL, NULL, NULL) == AWS_OP_SUCCESS); + ASSERT_TRUE(s_do_basic_provider_test(provider, 1, NULL, NULL, NULL, NULL) == AWS_OP_SUCCESS); aws_credentials_provider_release(provider); @@ -300,7 +318,7 @@ static int s_do_environment_credentials_provider_failure(struct aws_allocator *a struct aws_credentials_provider *provider = aws_credentials_provider_new_environment(allocator, &options); - ASSERT_TRUE(s_do_basic_provider_test(provider, 1, NULL, NULL, NULL) == AWS_OP_SUCCESS); + ASSERT_TRUE(s_do_basic_provider_test(provider, 1, NULL, NULL, NULL, NULL) == AWS_OP_SUCCESS); aws_credentials_provider_release(provider); @@ -1338,8 +1356,12 @@ static int s_credentials_provider_default_test(struct aws_allocator *allocator, ASSERT_TRUE( s_do_basic_provider_test( - provider, 1, s_access_key_id_test_value, s_secret_access_key_test_value, s_session_token_test_value) == - AWS_OP_SUCCESS); + provider, + 1, + s_access_key_id_test_value, + s_secret_access_key_test_value, + s_session_token_test_value, + NULL) == AWS_OP_SUCCESS); /* * Verify that there's some caching before the environment by modifying the environment and requerying @@ -1350,8 +1372,12 @@ static int s_credentials_provider_default_test(struct aws_allocator *allocator, ASSERT_TRUE( s_do_basic_provider_test( - provider, 1, s_access_key_id_test_value, s_secret_access_key_test_value, s_session_token_test_value) == - AWS_OP_SUCCESS); + provider, + 1, + s_access_key_id_test_value, + s_secret_access_key_test_value, + s_session_token_test_value, + NULL) == AWS_OP_SUCCESS); aws_credentials_provider_release(provider);