-
Notifications
You must be signed in to change notification settings - Fork 747
feat: add handshake event #5635
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
base: main
Are you sure you want to change the base?
Conversation
| /* This is a special value assigned to handshake_start_epoch_ns to indicate that | ||
| * it has already been sent to the application and should not be sent again. | ||
| */ | ||
| #define HANDSHAKE_EVENT_SENT UINT64_C(1) << 63 |
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.
Pretty sure you need to include the stdint library in order to use this macro.
| * | ||
| * An event is not emitted if the handshake fails. | ||
| */ | ||
| S2N_API extern int s2n_config_set_handshake_event(struct s2n_config *config, s2n_event_on_handshake_cb callback); |
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.
Trying to understand, what's the purpose of the subscriber pointer? Is it just the void ctx pointer that we typically have for callbacks? Why wouldn't you just combine these two APIs so that the set_handshake_event takes a subscriber?
| Duration::from_nanos(self.0.handshake_end_ns - self.0.handshake_start_ns) | ||
| } | ||
|
|
||
| /// Handshake time, which just the amount of time synchronously spent in s2n_negotiate. |
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.
| /// Handshake time, which just the amount of time synchronously spent in s2n_negotiate. | |
| /// Handshake time, which is just the amount of time synchronously spent in s2n_negotiate. |
| b"good enough bytes for test", | ||
| SystemTime::UNIX_EPOCH, | ||
| )? | ||
| .enable_session_tickets(true)?; |
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.
Nit: you technically don't need this if you added a session ticket key.
| .enable_session_tickets(true)?; |
| * specific error for a null wall clock config just before the client hello callback. | ||
| * The test's assertions are weakened if this check is moved. | ||
| */ | ||
| POSIX_ENSURE(conn->config->wall_clock, S2N_ERR_CONFIG_NULL_BEFORE_CH_CALLBACK); |
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.
Why is this change needed?
| EXPECT_NOT_NULL(default_config = s2n_fetch_default_config()); | ||
|
|
||
| /* s2n_config_new() matches s2n_fetch_default_config() */ | ||
| if (default_config->security_policy != config->security_policy) { |
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.
I don't know why you need this code change anymore since you fixed the problem?
| } | ||
|
|
||
| int s2n_config_set_subscriber(struct s2n_config *config, void *subscriber) | ||
| { |
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're missing null checks on both of these. Purposeful?
| * specific error for a null wall clock config just before the client hello callback. | ||
| * The test's assertions are weakened if this check is moved. | ||
| */ | ||
| POSIX_ENSURE(conn->config->wall_clock, S2N_ERR_CONFIG_NULL_BEFORE_CH_CALLBACK); |
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.
What if conn->config is null? 👀
| { | ||
| RESULT_ENSURE_REF(conn); | ||
| RESULT_ENSURE_REF(conn->config); | ||
| RESULT_ENSURE_REF(conn->config); |
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.
Duplicate check: it should be RESULT_ENSURE_REF(event)?
| { | ||
| BEGIN_TEST(); | ||
|
|
||
| if (!s2n_is_tls13_fully_supported()) { |
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.
Do we expect the event subscriber to be used with TLS 1.2? If so, it might be better to include that in the test?
|
|
||
| event->protocol_version = s2n_connection_get_actual_protocol_version(conn); | ||
| event->cipher = s2n_connection_get_cipher(conn); | ||
| s2n_connection_get_key_exchange_group(conn, &event->group); |
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.
Maybe add a RESULT_GUARD_POSIX to this call?
Edit: After looking into the RSA rust test, seems like the getter will return INVALID_STATE error in this case. That's why we don't check the error?
Goal
Emit a "handshake event", allowing customers to observe multiple pieces of information about the handshake.
Why
Currently customers have to call large numbers of individual "getter" APIs to gather information about the handshake. We expect that with this event structure will eventually be used to aggregate metrics for e.g. emission to CloudWatch.
How
The handshake is emitted to the application through a callback.
Callouts
s2n_event_handshakevss2n_handshake_event? I went with the former because it felt more neatly namespaced.This is adding new code in the hotpath, but it has a minimal impact
Testing
Unit tests, and self-talk tests in the rust bindings.
The tests for this cover a large API surface area, which is tedious to cover in C. Therefore I deliberately have most of the testing in Rust.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.