Skip to content

support proxy db tunnel mfa access#16958

Merged
GavinFrazar merged 28 commits intomasterfrom
gavinfrazar/proxy_db_tunnel_mfa_access
Oct 7, 2022
Merged

support proxy db tunnel mfa access#16958
GavinFrazar merged 28 commits intomasterfrom
gavinfrazar/proxy_db_tunnel_mfa_access

Conversation

@GavinFrazar
Copy link
Copy Markdown
Contributor

@GavinFrazar GavinFrazar commented Oct 4, 2022

Closes #12538

This PR adds MFA support for tsh proxy db --tunnel - the basic problem with MFA is that the certs are short-lived and expire after 1 minute, which means the local proxy only worked for 1 minute before this PR.

I added middleware to alpnproxy.LocalProxy which is invoked when the proxy starts and then on each new connection to check/renew database certs.

The database certs are kept in memory only, in preparation for approval of RFD 90 #16739.
The main thing I've left out of this PR is adjusting the TTL for database mfa certs, as that will required RFD approval before implementing.
edit: For now, the UX improves from a broken local proxy every minute, to an MFA check every minute. The RFD will significantly improve the UX further, I'm making this PR sooner than RFD approval since the middleware is needed to unblock Teleport Connect team.

@ravicious

edit:

UX Change

Before

local proxy:

[I] [14:33:33] gavin@mac ~/work/teleport  
$ tsh proxy db --port 8080 --tunnel teleport-mysql                                                  (base) 
Tap any security key
Started authenticated tunnel for the MySQL database "teleport-mysql" in cluster "gavin-dev.cloud.gravitational.io" on 127.0.0.1:8080.

Use the following command to connect to the database:
  $ mysql --port 8080 --host localhost --protocol TCP

mysql:

[I] [14:32:36] gavin@mac ~/work/teleport  
$ echo "select 1;" | mysql -h localhost -P 8080 --protocol TCP -u teleport50
1
1
[I] [14:34:36] gavin@mac ~/work/teleport  
$ echo "select 1;" | mysql -h localhost -P 8080 --protocol TCP -u teleport50
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 57

After:

local proxy:

[I] [14:31:26] gavin@mac ~/work/teleport  
$ tsh proxy db --port 8080 --tunnel teleport-mysql
Started authenticated tunnel for the MySQL database "teleport-mysql" in cluster "gavin-dev.cloud.gravitational.io" on 127.0.0.1:8080.

Use the following command to connect to the database:
  $ mysql --port 8080 --host localhost --protocol TCP
MFA is required to access database "teleport-mysql"
Tap any security key
Database certificate renewed: valid until 2022-10-05T21:32:30Z [valid for 1m0s]
MFA is required to access database "teleport-mysql"
Tap any security key
Database certificate renewed: valid until 2022-10-05T21:33:32Z [valid for 1m0s]

mysql:

[I] [14:31:41] gavin@mac ~/work/teleport  
$ echo "select 1;" | mysql -h localhost -P 8080 --protocol TCP -u teleport50
1
1
[I] [14:32:30] gavin@mac ~/work/teleport  
$ echo "select 1;" | mysql -h localhost -P 8080 --protocol TCP -u teleport50
1
1

And local proxy without MFA required (doesn't print a prompt context message before "Tap any security key"):

[I] [14:35:38] gavin@mac ~/work/teleport  
$ tsh proxy db --port 8080 --tunnel teleport-mysql
Started authenticated tunnel for the MySQL database "teleport-mysql" in cluster "gavin-dev.cloud.gravitational.io" on 127.0.0.1:8080.

Use the following command to connect to the database:
  $ mysql --port 8080 --host localhost --protocol TCP
Database certificate renewed: valid until 2022-10-06T07:27:21Z [valid for 9h52m0s]

OTP local proxy works too, but you need to pass an mfa auth preference (this is true for tsh db login as well)

$ tsh proxy db --port 8080 --tunnel teleport-mysql --auth=local --mfa-mode=otp
Started authenticated tunnel for the MySQL database "teleport-mysql" in cluster "gavin-dev.cloud.gravitational.io" on 127.0.0.1:8080.

Use the following command to connect to the database:
  $ mysql --port 8080 --host localhost --protocol TCP
MFA is required to access database "teleport-mysql"
Enter an OTP code from a device:
Database certificate renewed: valid until 2022-10-06T00:16:11Z [valid for 1m0s]
MFA is required to access database "teleport-mysql"
Enter an OTP code from a device:
Database certificate renewed: valid until 2022-10-06T00:17:18Z [valid for 1m0s]

@GavinFrazar GavinFrazar added tsh tsh - Teleport's command line tool for logging into nodes running Teleport. database-access Database access related issues and PRs feature-request Used for new features in Teleport, improvements to current should be #enhancements c-jm Internal Customer Reference labels Oct 4, 2022
@GavinFrazar GavinFrazar marked this pull request as ready for review October 4, 2022 01:34
@github-actions github-actions Bot requested review from ryanclark and zmb3 October 4, 2022 01:34
@GavinFrazar GavinFrazar changed the title proxy db tunnel mfa access support proxy db tunnel mfa access Oct 4, 2022
Comment thread lib/srv/alpnproxy/middleware.go
Comment thread integration/proxy/proxy_test.go Outdated
Comment thread lib/srv/alpnproxy/local_proxy.go Outdated
Comment thread lib/srv/alpnproxy/local_proxy.go Outdated
Comment thread lib/srv/alpnproxy/middleware.go Outdated
Comment thread lib/utils/certs.go
Comment thread tool/tsh/db.go
Comment thread tool/tsh/db.go
Comment thread lib/srv/alpnproxy/local_proxy.go Outdated
Comment thread lib/srv/alpnproxy/middleware.go Outdated
@smallinsky smallinsky self-requested a review October 5, 2022 15:25
@GavinFrazar
Copy link
Copy Markdown
Contributor Author

@greedy52 @smallinsky this is ready I think.

I've addressed your feedback regarding adding some context before prompting the user for MFA and I've made the integration test more robust using a fake clock to mock cert expiration.

@smallinsky
Copy link
Copy Markdown
Contributor

@GavinFrazar
In case of normal flow without MFA can we skip renewal of database certs if certs was already generated and are valid ?
For instance:
The certs generated by tsh db connect --db-user=marek --db-name=postgres postgres01

➜  tsh git:(gavinfrazar/proxy_db_tunnel_mfa_access) ✗ ./tsh db connect --db-user=marek --db-name=postgres postgres01
psql (14.4, server 13.4)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, bits: 128, compression: off)
Type "help" for help.

can be reused for tsh proxy db though in current flow always renews the certs:

postgres=> ^D\q
➜  tsh git:(gavinfrazar/proxy_db_tunnel_mfa_access) ✗ ./tsh proxy db postgres01 --tunnel  -p 1111
Started authenticated tunnel for the PostgreSQL database "postgres01" in cluster "root" on 127.0.0.1:1111.

Use the following command to connect to the database:
  $ psql postgres://marek@localhost:1111/postgres

Local proxy tunnel requires credentials to access database "postgres01"
Local proxy tunnel credentials successfully renewed

Also the:

``Local proxy tunnel requires credentials to access database "postgres01"` log entry might be a bit confusing for a user. I would keep this more like a debug log because no user action is needed in this case.

In case of MFA flow right now following message is printed:

local proxy tunnel requires credentials to access database "teleport-mysql"
Enter an OTP code from a device:

Could we emphasise in the log entry that local proxy that this is MFA flow ?

@xinding33 Could you take a look at UX changes ?

Comment thread lib/tlsca/ca.go Outdated
This is so we can check if the error is recoverable while preparing
local proxy options. A tunneled local proxy can ignore the error because
it does not rely on cert files - it can just renew its certs if
necessary.
@GavinFrazar
Copy link
Copy Markdown
Contributor Author

@smallinsky

In case of normal flow without MFA can we skip renewal of database certs if certs was already generated and are valid ?

Done.

Could we emphasize in the log entry that local proxy that this is MFA flow ?

Done. See:

MFA is required to access database "teleport-mysql"
Tap any security key
Database certificate renewed: valid until 2022-10-06T18:23:53Z [valid for 1m0s]

Copy link
Copy Markdown
Contributor

@smallinsky smallinsky left a comment

Choose a reason for hiding this comment

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

Linter seems to fail on a = a + 1 rule but otherwise LGTM.

Comment thread lib/client/mfa.go Outdated
@github-actions github-actions Bot removed request for ryanclark and zmb3 October 7, 2022 16:02
@GavinFrazar GavinFrazar enabled auto-merge (squash) October 7, 2022 19:46
@GavinFrazar GavinFrazar merged commit ba7df65 into master Oct 7, 2022
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Oct 7, 2022

@GavinFrazar See the table below for backport results.

Branch Result
branch/v11 Create PR

@GavinFrazar GavinFrazar deleted the gavinfrazar/proxy_db_tunnel_mfa_access branch October 8, 2022 01:19
Comment thread lib/srv/alpnproxy/local_proxy.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c-jm Internal Customer Reference database-access Database access related issues and PRs feature-request Used for new features in Teleport, improvements to current should be #enhancements 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.

Add support for 'tsh proxy db --tunnel' MFA access flow.

4 participants