Skip to content
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

Go client authentication support #3584

Merged
merged 11 commits into from
Mar 24, 2023
Merged

Conversation

chipkent
Copy link
Member

@chipkent chipkent commented Mar 22, 2023

Support authentication in the go client.

Resolves #3523

go/pkg/client/client.go Outdated Show resolved Hide resolved
jcferretti
jcferretti previously approved these changes Mar 22, 2023
go/pkg/client/tokens.go Outdated Show resolved Hide resolved
ticker := time.NewTicker(timeout)

go func() {
for {
Copy link
Contributor

@kosak kosak Mar 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In C++ we did things a little differently. You may or may not decide they are important enough to do.

Cristian and I were quite worried about the case where a message might be lost, dropped, or massively delayed. Sending handshakes at a fixed interval, as you do here, is only reliable if they are all delivered, and delivered in a timely fashion.

To try to be more robust about this, we used the following approach instead.

  1. We snoop all request/response traffic and we notice changes in auth token as they happen. This means when there is other traffic we don't bother sending a handshake at all, because we were able to snoop the token from some other response. We only do a handshake if there has been a timeout-sized period of no traffic at all.
  2. The code basically has two states: normal (I have received some kind of response in the last timeout period) and handshaking (I've not received any kind of response in the last timeout period). When it enters the "handshaking" state, the code sends handshakes pretty aggressively (like once every 5 seconds). This allows the token refresh thing to be somewhat robust against network freezes or connection drops. But then, any response from the server (whether a normal response or a handshake response) tends to put the code back into the "normal" state, so in the common case you only send one handshake and then drop back to the normal state.
  3. In order to account for the vagaries of round trip time and connection drops, the code keeps track of timeouts based on the local time when a (request or handshake) was sent rather than when a response was received. For example, if I sent a (request or handshake) at 12:00:00 and I receive a response at 12:00:20, I will do my timeout calculations based on when I sent the request, not when I received the response. In other words if the timeout is 5 minutes, I will consider going to handshake mode at 12:05:00, not 12:05:20.

Basically the C++ code follows this kind of pseudocode:

At any request

Note current local time
send the request

At any response to a request or a handshake

note the new auth header (maybe don't bother copying it if it hasn't changed)
reset the `handshake deadline` to the (time of the corresponding request) plus 5 minutes

The handshake thread:

forever:
  sleep until handshake deadline
  if current time < handshake deadline  # deadline has advanced in the meantime
     continue loop
  note current handshake request time
  send handshake message asynchronously
  set handshake deadline to now + 5 seconds
  # the above is pessimistic, because the response to this handshake message,
  # if received, will undergo standard auth header and deadline processing and
  # will advance the deadline forward ~5 minutes
end forever

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jcferretti proposed (and I agree) that we should defer this work to a future PR.

go/pkg/client/client.go Outdated Show resolved Hide resolved
go/pkg/client/client.go Outdated Show resolved Hide resolved
go/internal/test_tools/test_tools.go Show resolved Hide resolved
go/pkg/client/tokens.go Outdated Show resolved Hide resolved
go/pkg/client/tokens.go Outdated Show resolved Hide resolved
jcferretti
jcferretti previously approved these changes Mar 24, 2023
Copy link
Contributor

@kosak kosak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple more small things

go/pkg/client/client.go Outdated Show resolved Hide resolved
func GetAuth() string {
auth := os.Getenv("DH_AUTH")
if auth == "" {
return "Anonymous"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be Constants.DefaultAuth (or whatever) rather than the literal string "Anonymous"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be using the constant. This is set to match the DH instance that is spun up to test against. We have no guarantee that the instance will be using the default connection mechanism, so I'm not completely comfortable linking them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My opinion is weak on this, so if you think it should be changed, I will.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not deeply invested in either choice. I assumed it was an oversight. If not, that's fine.

@chipkent chipkent enabled auto-merge (squash) March 24, 2023 16:07
@chipkent chipkent merged commit b74519d into deephaven:main Mar 24, 2023
@chipkent chipkent deleted the 3523_go_flight_auth branch March 24, 2023 16:15
@github-actions github-actions bot locked and limited conversation to collaborators Mar 24, 2023
@deephaven-internal
Copy link
Contributor

@chipkent
Copy link
Member Author

This PR will break example Go clients, and these clients are not being automatically run in our docs tests.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Go client should migrate to flight auth
4 participants