Skip to content

Add mutex for certs in local proxy#18278

Merged
GavinFrazar merged 17 commits intomasterfrom
gavinfrazar/fix-data-race-in-local-proxy
Nov 18, 2022
Merged

Add mutex for certs in local proxy#18278
GavinFrazar merged 17 commits intomasterfrom
gavinfrazar/fix-data-race-in-local-proxy

Conversation

@GavinFrazar
Copy link
Copy Markdown
Contributor

@GavinFrazar GavinFrazar commented Nov 8, 2022

This is a small PR that adds a mutex to guard get/set certs in the alpn local proxy.

The purpose of this PR is to eliminate the possibility of a data race by using a mutex and providing a safe API for packages outside of alpnproxy. The PR was small, but @zmb3 correctly pointed out that GetCerts was basically a bug waiting to happen, since the caller must know to not mutate the slice returned. Therefore I refactored and eliminated the public GetCerts method in favor of having the local proxy check its own certs.

This PR moves database cert checking out of the local proxy middleware and into the local proxy itself. The middleware can instead call the local proxy's method to check for cert validity, while still handling cert renewal if needed.

In #16958 I had added a mutex and the get/set methods on local proxy for the purpose of protecting reads/writes to the TLS certs, but I removed the mutex when I moved the middleware out the goroutine spawned in lib/srv/alpnproxy/LocalProxy.Start. What I failed to account for was that the certs are read once and copied inside the function that handles the downstream connection in that goroutine. I noticed this when reviewing this code today. I was unable to trip the go race detector in tests unless I modified the local proxy code to call GetCerts in a tight loop. I think it's because there is a very small window where the race can actually happen, but regardless we should guard the certs with a mutex.

Tests

  1. I added a test that catches the data race that was possible without using a mutex.
  2. I added a test for the db cert check function itself.
  3. I refactored the local proxy integration test.

Copy link
Copy Markdown
Member

@ryanclark ryanclark left a comment

Choose a reason for hiding this comment

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

This could be an RWMutex instead

Comment thread lib/srv/alpnproxy/local_proxy.go Outdated
Comment thread lib/srv/alpnproxy/local_proxy.go Outdated
Comment thread lib/srv/alpnproxy/local_proxy.go Outdated
GavinFrazar and others added 3 commits November 8, 2022 13:03
Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>
Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>
Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>
@GavinFrazar
Copy link
Copy Markdown
Contributor Author

I think you're right, the certs will mostly be read not written to, so RWMutex makes more sense

@GavinFrazar
Copy link
Copy Markdown
Contributor Author

@ryanclark I used your suggestions, are there any other concerns?

Comment thread lib/srv/alpnproxy/local_proxy.go
@ravicious
Copy link
Copy Markdown
Member

I just did a quick check on a temp branch by rebasing my PR (#18259) on top of this one to see if the cert verification logic works for Connect and it works just fine.

I'll wait for this PR to get merged before I merge #18259.

Comment thread lib/srv/alpnproxy/local_proxy_test.go
@GavinFrazar GavinFrazar requested a review from zmb3 November 15, 2022 22:40
@GavinFrazar GavinFrazar enabled auto-merge (squash) November 17, 2022 20:28
Comment thread lib/srv/alpnproxy/helpers_test.go Outdated
Comment thread lib/srv/alpnproxy/local_proxy_test.go Outdated
@GavinFrazar GavinFrazar merged commit 5e1b452 into master Nov 18, 2022
@github-actions
Copy link
Copy Markdown
Contributor

@GavinFrazar See the table below for backport results.

Branch Result
branch/v11 Failed

@GavinFrazar GavinFrazar deleted the gavinfrazar/fix-data-race-in-local-proxy branch November 18, 2022 00:35
GavinFrazar added a commit that referenced this pull request Nov 18, 2022
* Add mutex for certs in local proxy

* Update lib/srv/alpnproxy/local_proxy.go

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>

* Update lib/srv/alpnproxy/local_proxy.go

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>

* Update lib/srv/alpnproxy/local_proxy.go

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>

* Move cert checking out of middleware into local proxy

* Configure a logger for local proxy

* Fixup imports

* Add tests for local proxy

* test for data race
* test for cert checking

* Update integration test for local proxy

* Mark err assert fns as helpers

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>
GavinFrazar added a commit that referenced this pull request Nov 22, 2022
* Add mutex for certs in local proxy

* Update lib/srv/alpnproxy/local_proxy.go

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>

* Update lib/srv/alpnproxy/local_proxy.go

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>

* Update lib/srv/alpnproxy/local_proxy.go

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>

* Move cert checking out of middleware into local proxy

* Configure a logger for local proxy

* Fixup imports

* Add tests for local proxy

* test for data race
* test for cert checking

* Update integration test for local proxy

* Mark err assert fns as helpers

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>

Co-authored-by: Ryan Clark <ryan.clark@goteleport.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants