-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enforce ECSCredentialsProvider IP Rules #234
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #234 +/- ##
==========================================
- Coverage 79.54% 79.43% -0.12%
==========================================
Files 33 33
Lines 5872 5907 +35
==========================================
+ Hits 4671 4692 +21
- Misses 1201 1215 +14 ☔ View full report in Codecov by Sentry. |
result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); | ||
result |= aws_byte_cursor_eq(&address, &eks_container_host_address); | ||
} else if (aws_host_utils_is_ipv6(address, false)) { | ||
/* Check for both the short form and long form of an IPv6 address to be safe. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: it would be cool if we had a function to convert these IP strings into their actual byte values
since there are even more ways to write these addresses (e.g. "0:0::1"), which are weird, but still legal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are getting these IP strings from a system call, and we can convert them back to byte values using an OS dependent system call and memcmp them (at least that's what ChatGPT told me). I can add a function to common, but the fact that we are getting these IPs from system calls, we discussed that it should be good enough to just compare both the short form and the long form and ignore the weird ones.
Testing the OS behavior for n different platforms led to the addition of an actual mock server, but unfortunately, GitHub runners don't support IPv6.
/* validate ip address if the connection manager is not mocked */ | ||
if (impl->function_table == g_aws_credentials_provider_http_function_table && | ||
!s_is_valid_remote_host_ip(ecs_user_data, connection)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't have the implementation skip functionality when it detects it's in a test
Do we need to add aws_http_connection_get_remote_endpoint() to the function_table?
@@ -57,6 +57,12 @@ add_test_case(credentials_provider_ecs_no_auth_token_success) | |||
add_test_case(credentials_provider_ecs_success_multi_part_doc) | |||
add_test_case(credentials_provider_ecs_real_new_destroy) | |||
|
|||
if(ENABLE_AUTH_MOCK_SERVER_TESTS) | |||
# TODO: Add IPv6 tests when the Github runner support it. See: https://github.com/actions/runner-images/issues/668 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could add the test, and have it return AWS_OP_SKIP if it fails due to lack of IPv6 support
aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL); | ||
s_aws_wait_for_credentials_result(); | ||
ASSERT_NULL(s_tester.credentials); | ||
ASSERT_TRUE(s_tester.error_code == AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trivial:
ASSERT_TRUE(s_tester.error_code == AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST); | |
ASSERT_INT_EQUALS(AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST, s_tester.error_code); |
it gives a nice printf about what we got, vs what was expected
aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL); | ||
s_aws_wait_for_credentials_result(); | ||
ASSERT_NOT_NULL(s_tester.credentials); | ||
ASSERT_TRUE(s_tester.error_code == AWS_OP_SUCCESS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
likewise
@@ -536,6 +557,87 @@ static int s_credentials_provider_ecs_basic_success(struct aws_allocator *alloca | |||
|
|||
AWS_TEST_CASE(credentials_provider_ecs_basic_success, s_credentials_provider_ecs_basic_success); | |||
|
|||
static int s_credentials_provider_ecs_mocked_server_basic_ipv4_invalid(struct aws_allocator *allocator, void *ctx) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's already a system for mocking HTTP calls in auth tests. Is there a really good reason for adding another?
bool result = false; | ||
|
||
const struct aws_byte_cursor address = | ||
aws_byte_cursor_from_c_str(aws_http_connection_get_remote_endpoint(connection)->address); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This technique won't work with many other HTTP clients. It's uncommon that you have a chance to inspect the IP before making the actual request.
just asking the host_resolver directly would be more portable
I get that you're trying to avoid additional calls to the resolver. You could do like the Rust SDK and only validate when full-uri is passed in by the user.
Is the fact that this relies on the HTTP client what's forcing you to add a 2nd way of mocking HTTP calls?
Co-authored-by: Michael Graeb <[email protected]>
Closing in favor of #238 |
Description of changes:
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.