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

Client Certificate Authentication for GCP Cloud SQL #9991

Merged
merged 10 commits into from
Jan 31, 2022
Merged

Conversation

jimbishopp
Copy link
Contributor

Closes #8217

Allow users to secure GCP Cloud SQL instances by setting "Allow only SSL connections", which enforces client certificate authentication.

This implementation does not require any configuration changes for Teleport users. Teleport will detect whether client certificate authentication is required and handle either case automatically.

Client certificates are ephemeral. They are created for every connection by calling the GCP Cloud SQL API's GenerateEphemeralCert function. Certificates are only created when the destination Cloud SQL instance is configured to require client certificate authentication. The configuration is detected by requesting instance settings from the GCP Cloud SQL API on every connection attempt.

A special case was implemented for MySQL. MySQL servers in GCP Cloud SQL do not trust the ephemeral certificate's CA but GCP Cloud Proxy does. To work around this issue, the implementation will connect to the MySQL Cloud Proxy port using a TLS dialer instead of the default MySQL port when client certificate authentication is required.

The common.CloudClients interface and implementation now return an interface (GCPSQLAdminClient) from the GetGCPSQLAdminClient function instead of the GCP client's sqladmin.Service. Returning an interface simplified calling code and allowed for the client to be mocked for testing.

Existing GCP Cloud SQL tests are configured to not require client certificate authentication by default. A new test named TestGCPRequireSSL was created to simulate client certificate authentication for both Postgres and MySQL. This required some minor changes to the test server code.

A new ConnectWithDialer function was added to the github.com/gravitational/go-mysql fork. This function is available upstream in v1.4.0 but other changes upstream resulted in a number of errors and a panic processing network packets. So instead of upgrading, the dialer function was copied to the Teleport fork and a custom version was created instead: v1.1.1-teleport.1. The errors found will be documented in another issue.

Teleport documentation will be updated in another PR.

@github-actions github-actions bot added the database-access Database access related issues and PRs label Jan 27, 2022
@jimbishopp jimbishopp enabled auto-merge (squash) January 27, 2022 20:05
@jimbishopp jimbishopp self-assigned this Jan 27, 2022
@jimbishopp jimbishopp changed the title Client Certificate Auth for GCP Cloud SQL Client Certificate Authentication for GCP Cloud SQL Jan 27, 2022
Copy link
Collaborator

@r0mant r0mant left a comment

Choose a reason for hiding this comment

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

Implementation looks good mostly, just need to ensure backwards compatibility.

lib/srv/db/mysql/engine.go Outdated Show resolved Hide resolved
lib/srv/db/mysql/engine.go Outdated Show resolved Hide resolved
lib/srv/db/mysql/engine.go Outdated Show resolved Hide resolved
lib/srv/db/postgres/engine.go Outdated Show resolved Hide resolved
lib/srv/db/common/gcp.go Outdated Show resolved Hide resolved
lib/srv/db/mysql/engine.go Outdated Show resolved Hide resolved
lib/srv/db/mysql/engine.go Outdated Show resolved Hide resolved
auto-merge was automatically disabled January 28, 2022 22:08

Pull Request is not mergeable

@jimbishopp jimbishopp enabled auto-merge (squash) January 28, 2022 22:27
@jimbishopp jimbishopp disabled auto-merge January 29, 2022 00:05
@jimbishopp jimbishopp force-pushed the jim/gcp-mtls branch 2 times, most recently from 59769e2 to 3e075aa Compare January 29, 2022 00:21
Allow users to secure Cloud SQL instances by setting
"Allow only SSL connections".

Generate client certificates using the GenerateEphemeralCert function in
the Google API (added to the Connect service in v0.51).

Workaround issue with mysql's cloud instance not trusting the generated
cert's CA by connecting to the cloud proxy port instead.
@jimbishopp
Copy link
Contributor Author

@r0mant @smallinsky Backwards compatibility looks like it is working and I was able to backport to v8. Users are able to login with their current IAM configs as long as SSL is disabled. When enabled, an error message is displayed letting them know they need to update their permissions.

@jimbishopp jimbishopp enabled auto-merge (squash) January 31, 2022 15:48
lib/srv/db/cloud/gcp.go Outdated Show resolved Hide resolved
@jimbishopp jimbishopp disabled auto-merge January 31, 2022 16:42
@jimbishopp jimbishopp enabled auto-merge (squash) January 31, 2022 17:21
@r0mant
Copy link
Collaborator

r0mant commented Jan 31, 2022

@jimbishopp Once this gets approved/merged, let's please backport to v8 as well. Thanks!

@jimbishopp jimbishopp merged commit 4511f7a into master Jan 31, 2022
@jimbishopp jimbishopp deleted the jim/gcp-mtls branch January 31, 2022 19:52
jimbishopp added a commit that referenced this pull request Jan 31, 2022
Allow users to secure GCP Cloud SQL instances by setting "Allow only SSL
connections", which enforces client certificate authentication.

This implementation does not require any configuration changes for Teleport
users. Teleport will detect whether client certificate authentication is
required and handle either case automatically.

Client certificates are ephemeral. They are created for every connection by
calling the GCP Cloud SQL API's GenerateEphemeralCert function. Certificates
are only created when the destination Cloud SQL instance is configured to
require client certificate authentication. The configuration is detected by
requesting instance settings from the GCP Cloud SQL API on every connection
attempt.

A special case was implemented for MySQL. MySQL servers in GCP Cloud SQL do not
trust the ephemeral certificate's CA but GCP Cloud Proxy does. To work around
this issue, the implementation will connect to the MySQL Cloud Proxy port using
a TLS dialer instead of the default MySQL port when client certificate
authentication is required.

The common.CloudClients interface and implementation now return an interface
(GCPSQLAdminClient) from the GetGCPSQLAdminClient function instead of the GCP
client's sqladmin.Service. Returning an interface simplified calling code and
allowed for the client to be mocked for testing.

Existing GCP Cloud SQL tests are configured to not require client certificate
authentication by default. A new test named TestGCPRequireSSL was created to
simulate client certificate authentication for both Postgres and MySQL. This
required some minor changes to the test server code.

A new ConnectWithDialer function was added to the
github.com/gravitational/go-mysql fork. This function is available upstream in
v1.4.0 but other changes upstream resulted in a number of errors and a panic
processing network packets. So instead of upgrading, the dialer function was
copied to the Teleport fork and a custom version was created instead:
v1.1.1-teleport.1.
@jimbishopp
Copy link
Contributor Author

Added issue to track failed upgrade of go-mysql to v1.4.

#10067

jimbishopp added a commit that referenced this pull request Feb 1, 2022
* Vendor go-mysql update

* Client Certificate Authentication for GCP Cloud SQL (#9991)

Allow users to secure GCP Cloud SQL instances by setting "Allow only SSL
connections", which enforces client certificate authentication.

This implementation does not require any configuration changes for Teleport
users. Teleport will detect whether client certificate authentication is
required and handle either case automatically.

Client certificates are ephemeral. They are created for every connection by
calling the GCP Cloud SQL API's GenerateEphemeralCert function. Certificates
are only created when the destination Cloud SQL instance is configured to
require client certificate authentication. The configuration is detected by
requesting instance settings from the GCP Cloud SQL API on every connection
attempt.

A special case was implemented for MySQL. MySQL servers in GCP Cloud SQL do not
trust the ephemeral certificate's CA but GCP Cloud Proxy does. To work around
this issue, the implementation will connect to the MySQL Cloud Proxy port using
a TLS dialer instead of the default MySQL port when client certificate
authentication is required.

The common.CloudClients interface and implementation now return an interface
(GCPSQLAdminClient) from the GetGCPSQLAdminClient function instead of the GCP
client's sqladmin.Service. Returning an interface simplified calling code and
allowed for the client to be mocked for testing.

Existing GCP Cloud SQL tests are configured to not require client certificate
authentication by default. A new test named TestGCPRequireSSL was created to
simulate client certificate authentication for both Postgres and MySQL. This
required some minor changes to the test server code.

A new ConnectWithDialer function was added to the
github.com/gravitational/go-mysql fork. This function is available upstream in
v1.4.0 but other changes upstream resulted in a number of errors and a panic
processing network packets. So instead of upgrading, the dialer function was
copied to the Teleport fork and a custom version was created instead:
v1.1.1-teleport.1.
jimbishopp added a commit that referenced this pull request Feb 2, 2022
jimbishopp added a commit that referenced this pull request Feb 3, 2022
jimbishopp added a commit that referenced this pull request Feb 3, 2022
jimbishopp added a commit that referenced this pull request Feb 3, 2022
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for GCP Cloud SQL client certificate auth
3 participants