Session expired message for tsh proxy db#15398
Conversation
|
@smallinsky @ravicious I have tested this for |
| } | ||
|
|
||
| if arg.onNewConnection != nil { | ||
| dbCert, err := certFromPath(arg.profile.DatabaseCertPathForCluster(arg.cliConf.SiteName, arg.routeToDatabase.ServiceName)) |
There was a problem hiding this comment.
Does the cert can be reissued without restarting the local proxy ? If yes the dbCert will contains the stale cert data. Reading the cert from disk for each connection is not effective but maybe we can load cert periodically once per some timeout ?
There was a problem hiding this comment.
Does the cert can be reissued without restarting the local proxy?
Yes, the cert can be reissued if the user runs other tsh commands (or if Teleport Connect tries to do something). However, the LocalProxy is also using the stale cert with today's implementation.
Do we also want to add the functionality to overwrite the cert LocalProxy is using (without restarting) in this PR? There are many approaches we can do too.
There was a problem hiding this comment.
Can we cache the last cert loaded and check if it has expired? If it has expired then prompt user for credentials to reissue the cert.
ravicious
left a comment
There was a problem hiding this comment.
The approach works for me in general. I have a proof of concept of tshd -> Connect communication where Connect calls tshd to establish a server stream. Then I just put stuff on a channel within the callback and whatever is put on the channel is sent over the stream. I just need to figure out a couple of nuances around errors and reconnecting.
I haven't got around to replicating the cert expiration logic in Connect yet. I'm glad that I didn't because guessing from Marek's comment maybe we'll need to take a slightly different approach in Connect as well. 😏
| onNewConnection := func(dbCert *x509.Certificate, lp *alpnproxy.LocalProxy, conn net.Conn) { | ||
| if time.Now().After(dbCert.NotAfter) { | ||
| fmt.Fprintln(cf.Stdout()) | ||
| fmt.Fprintln(cf.Stdout(), "Your database session is expired. Please restart the local proxy.") |
There was a problem hiding this comment.
| fmt.Fprintln(cf.Stdout(), "Your database session is expired. Please restart the local proxy.") | |
| fmt.Fprintln(cf.Stdout(), "Your database session has expired. Please restart the local proxy.") |
I think "has" is more correct here though I'm not 100% sure.
| // | ||
| // Note that the callback blocks handling of the connection. |
There was a problem hiding this comment.
I see this note but I just want to clarify that your intention was to block the LocalProxy.Start for {...} loop entirely or just an individual connection? We are doing the former - but if that was your intention could you explain why not call the callback inside the spawned goroutine just before calling l.handleDownstreamConnection?
There was a problem hiding this comment.
good question. I guess this note is inaccurate. In current use cases, I think we want to block the LocalProxy.Start, meaning when detecting a certain situation by this callback, there is no point in accepting another new connection until the situation is resolved. For the MFA flow, feel free to do anything that works for you.
| onNewConnection := func(dbCert *x509.Certificate, lp *alpnproxy.LocalProxy, conn net.Conn) { | ||
| if time.Now().After(dbCert.NotAfter) { | ||
| fmt.Fprintln(cf.Stdout()) | ||
| fmt.Fprintln(cf.Stdout(), "Your database session is expired. Please restart the local proxy.") |
There was a problem hiding this comment.
Why should they restart the local proxy? If the database cli is providing the certs and the local proxy is just forwarding, can't they just use tsh db login and it will work? This works without --tunnel already, they just need to know to do it
There was a problem hiding this comment.
This message is shown at the end of tsh proxy db command to ask the user to rerun whatever tsh proxy db command they are currently running.
There was a problem hiding this comment.
Oh I see - does tsh proxy db not work with reissued certs if it is started with expired certs? I actually haven't tried that: I only tried waiting for the 1 minute cert to expire
|
@greedy52 Any plans to merge this in? I might need a week or two more but I'm getting close to making a PR which utilizes this new callback. |
Callback will be added to close #12538 although we're waiting on RFD now - but I'll see if I can add that sooner than the RFD approval since the RFD is mainly about removing the 1 minute cert TTL for per-session-mfa db access |
I'd appreciate if you could add it sooner since I'll be adding stuff to handle expired certs before dealing with per-session MFA in Connect. Well, unless you think that on your side addressing both problems at the same time would be more beneficial. |
|
Sorry guys for these troubles. @GavinFrazar by any chance you have a prototype of how the callback will look like for your change? @ravicious is it ok for you to include the changes from |
|
I'm going to make the PR to add the callback for the local proxy today. I'm just really struggling with setting up an integration test for refreshing expired certs - that is what's blocking me. Basic problem is mocking time, because TLS handshakes use the real system clock. |
|
PR adding callbacks: #16958 |
|
closed in favor of #16958 |
No description provided.