Skip to content

Session expired message for tsh proxy db#15398

Closed
greedy52 wants to merge 3 commits intomasterfrom
STeve/14180_connection_callback
Closed

Session expired message for tsh proxy db#15398
greedy52 wants to merge 3 commits intomasterfrom
STeve/14180_connection_callback

Conversation

@greedy52
Copy link
Copy Markdown
Contributor

No description provided.

@greedy52 greedy52 added tsh tsh - Teleport's command line tool for logging into nodes running Teleport. database-access Database access related issues and PRs labels Aug 10, 2022
@greedy52 greedy52 self-assigned this Aug 10, 2022
@greedy52
Copy link
Copy Markdown
Contributor Author

@smallinsky @ravicious I have tested this for tsh proxy db and it works as expected when a new connection comes. Let me know what you think about the approach. If good I will open this for review.

Comment thread tool/tsh/db.go
}

if arg.onNewConnection != nil {
dbCert, err := certFromPath(arg.profile.DatabaseCertPathForCluster(arg.cliConf.SiteName, arg.routeToDatabase.ServiceName))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Member

@ravicious ravicious left a comment

Choose a reason for hiding this comment

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

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. 😏

Comment thread tool/tsh/proxy.go
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.")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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.

@ravicious
Copy link
Copy Markdown
Member

@greedy52 #16043 makes use of OnNewConnection, I'd appreciate if you could take a look at it some time next week!

Comment on lines +80 to +81
//
// Note that the callback blocks handling of the connection.
Copy link
Copy Markdown
Contributor

@GavinFrazar GavinFrazar Sep 7, 2022

Choose a reason for hiding this comment

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

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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment thread tool/tsh/proxy.go
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.")
Copy link
Copy Markdown
Contributor

@GavinFrazar GavinFrazar Sep 7, 2022

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

@GavinFrazar GavinFrazar Sep 7, 2022

Choose a reason for hiding this comment

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

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

@ravicious
Copy link
Copy Markdown
Member

@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.

@GavinFrazar
Copy link
Copy Markdown
Contributor

@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

@ravicious
Copy link
Copy Markdown
Member

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.

@greedy52
Copy link
Copy Markdown
Contributor Author

greedy52 commented Oct 3, 2022

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 lib/srv/alpnproxy/local_proxy.go from this PR directly in your change? It's reasonably small and shouldn't break anything so i think it's safe for you to check it in, in case Gavin's change comes after yours.

@GavinFrazar
Copy link
Copy Markdown
Contributor

GavinFrazar commented Oct 3, 2022

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.

@GavinFrazar
Copy link
Copy Markdown
Contributor

PR adding callbacks: #16958

@greedy52
Copy link
Copy Markdown
Contributor Author

greedy52 commented Oct 4, 2022

closed in favor of #16958

@greedy52 greedy52 closed this Oct 4, 2022
@greedy52 greedy52 deleted the STeve/14180_connection_callback branch October 21, 2022 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

database-access Database access related issues and PRs tsh tsh - Teleport's command line tool for logging into nodes running Teleport.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants