-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[v8] Client Certificate Authentication for GCP Cloud SQL (#10059)
* 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.
- Loading branch information
1 parent
6cbe24c
commit 065d524
Showing
20 changed files
with
580 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
Copyright 2022 Gravitational, Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package cloud | ||
|
||
import ( | ||
"context" | ||
"crypto/tls" | ||
|
||
"github.com/gravitational/teleport/lib/srv/db/common" | ||
"github.com/gravitational/trace" | ||
) | ||
|
||
// GetGCPRequireSSL requests settings for the project/instance in session from GCP | ||
// and returns true when the instance requires SSL. An access denied error is | ||
// returned when an unauthorized error is returned from GCP. | ||
func GetGCPRequireSSL(ctx context.Context, sessionCtx *common.Session, gcpClient common.GCPSQLAdminClient) (requireSSL bool, err error) { | ||
dbi, err := gcpClient.GetDatabaseInstance(ctx, sessionCtx) | ||
if err != nil { | ||
err = common.ConvertError(err) | ||
if trace.IsAccessDenied(err) { | ||
return false, trace.Wrap(err, `Could not get GCP database instance settings: | ||
%v | ||
Make sure Teleport db service has "Cloud SQL Admin" GCP IAM role, | ||
or "cloudsql.instances.get" IAM permission.`, err) | ||
} | ||
return false, trace.Wrap(err, "Failed to get Cloud SQL instance information for %q.", common.GCPServerName(sessionCtx)) | ||
} else if dbi.Settings == nil || dbi.Settings.IpConfiguration == nil { | ||
return false, trace.BadParameter("Failed to find Cloud SQL settings for %q. GCP returned %+v.", common.GCPServerName(sessionCtx), dbi) | ||
} | ||
return dbi.Settings.IpConfiguration.RequireSsl, nil | ||
} | ||
|
||
// AppendGCPClientCert calls the GCP API to generate an ephemeral certificate | ||
// and adds it to the TLS config. An access denied error is returned when the | ||
// generate call fails. | ||
func AppendGCPClientCert(ctx context.Context, sessionCtx *common.Session, gcpClient common.GCPSQLAdminClient, tlsConfig *tls.Config) error { | ||
cert, err := gcpClient.GenerateEphemeralCert(ctx, sessionCtx) | ||
if err != nil { | ||
err = common.ConvertError(err) | ||
if trace.IsAccessDenied(err) { | ||
return trace.Wrap(err, `Cloud not generate GCP ephemeral client certificate: | ||
%v | ||
Make sure Teleport db service has "Cloud SQL Admin" GCP IAM role, | ||
or "cloudsql.sslCerts.createEphemeral" IAM permission.`, err) | ||
} | ||
return trace.Wrap(err, "Failed to generate GCP ephemeral client certificate for %q.", common.GCPServerName(sessionCtx)) | ||
} | ||
tlsConfig.Certificates = []tls.Certificate{*cert} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.