mirror of
https://github.com/gravitational/teleport
synced 2024-10-19 16:53:57 +00:00
Fix user mismatch in postgres backend (#12467)
Always set the user field of the database connection string to the same user defined in the CommonName field of the client certificate. The pgx library always includes a user field in the connection string and defaults to $USER. The database connection will fail when $USER is not the same as the value defined in the CommonName field of the client certificate.
This commit is contained in:
parent
95092dc0f8
commit
b96cff3acf
|
@ -18,6 +18,8 @@ package postgres
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -61,6 +63,17 @@ func (d *pgDriver) open(ctx context.Context, u *url.URL) (sqlbk.DB, error) {
|
|||
}
|
||||
connConfig.Logger = d.sqlLogger
|
||||
|
||||
// extract the user from the first client certificate in TLSConfig.
|
||||
if connConfig.TLSConfig != nil {
|
||||
connConfig.User, err = tlsConfigUser(connConfig.TLSConfig)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if connConfig.User == "" {
|
||||
return nil, trace.BadParameter("storage backend certificate CommonName field is blank; database username is required")
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to create backend database if it does not exist.
|
||||
err = d.maybeCreateDatabase(ctx, connConfig)
|
||||
if err != nil {
|
||||
|
@ -228,6 +241,19 @@ func convertError(err error) error {
|
|||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
// tlsConfigUser returns the user defined in the CommonName field of the first
|
||||
// client certificate in tlsConfig.
|
||||
func tlsConfigUser(tlsConfig *tls.Config) (user string, err error) {
|
||||
if tlsConfig == nil || len(tlsConfig.Certificates) == 0 || len(tlsConfig.Certificates[0].Certificate) == 0 {
|
||||
return "", trace.BadParameter("unable to extract user from TLS Config")
|
||||
}
|
||||
cert, err := x509.ParseCertificate(tlsConfig.Certificates[0].Certificate[0])
|
||||
if err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
return cert.Subject.CommonName, nil
|
||||
}
|
||||
|
||||
const (
|
||||
// errCodeUniqueConstraint means a duplicate key value violated a unique constraint.
|
||||
errCodeUniqueConstraint = "23505"
|
||||
|
|
Loading…
Reference in a new issue