Skip to content

Commit

Permalink
[v9] Fix user mismatch in postgres backend (#12553)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jimbishopp authored May 12, 2022
1 parent aadfd80 commit 2781abc
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/backend/postgres/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package postgres

import (
"context"
"crypto/tls"
"crypto/x509"
"database/sql"
"errors"
"fmt"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 2781abc

Please sign in to comment.