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:
Jim Bishopp 2022-05-10 09:41:05 -07:00 committed by GitHub
parent 95092dc0f8
commit b96cff3acf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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"