Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: lib/pq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.9.0
Choose a base ref
...
head repository: lib/pq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.10.0
Choose a head ref
  • 4 commits
  • 3 files changed
  • 3 contributors

Commits on Feb 12, 2021

  1. Support inline SSL certificates

    Presently, pq only supports SSL connections by
    loading PEM certificates from files on disk.
    There are some situations (for example integration
    with HashiCorp Vault) where it's not so feasible
    to load certificates from a file system, but better
    to store them in-memory.
    
    This patch lets you set ?sslinline=true in the
    connection string, which changes the behavior of
    the paramters sslrootcert, sslcert and sslkey, so
    they contain the contents of the certificates
    directly, instead of file names pointing to the
    certificates on disk.
    eirslett committed Feb 12, 2021
    Copy the full SHA
    b9bb726 View commit details
  2. remove empty line

    eirslett committed Feb 12, 2021
    Copy the full SHA
    b7c85ee View commit details
  3. Copy the full SHA
    1467baf View commit details
  4. Merge pull request #818 from eirslett/feature/ssl-inline

    Support inline SSL certificates
    maddyblue authored Feb 12, 2021
    Copy the full SHA
    072e83d View commit details
Showing with 34 additions and 8 deletions.
  1. +29 −3 ssl.go
  2. +2 −2 url.go
  3. +3 −3 url_test.go
32 changes: 29 additions & 3 deletions ssl.go
Original file line number Diff line number Diff line change
@@ -59,6 +59,9 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
return nil, err
}

// This pseudo-parameter is not recognized by the PostgreSQL server, so let's delete it after use.
delete(o, "sslinline")

// Accept renegotiation requests initiated by the backend.
//
// Renegotiation was deprecated then removed from PostgreSQL 9.5, but
@@ -83,6 +86,19 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
// in the user's home directory. The configured files must exist and have
// the correct permissions.
func sslClientCertificates(tlsConf *tls.Config, o values) error {
sslinline := o["sslinline"]
if sslinline == "true" {
cert, err := tls.X509KeyPair([]byte(o["sslcert"]), []byte(o["sslkey"]))
// Clear out these params, in case they were to be sent to the PostgreSQL server by mistake
o["sslcert"] = ""
o["sslkey"] = ""
if err != nil {
return err
}
tlsConf.Certificates = []tls.Certificate{cert}
return nil
}

// user.Current() might fail when cross-compiling. We have to ignore the
// error and continue without home directory defaults, since we wouldn't
// know from where to load them.
@@ -137,9 +153,19 @@ func sslCertificateAuthority(tlsConf *tls.Config, o values) error {
if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 {
tlsConf.RootCAs = x509.NewCertPool()

cert, err := ioutil.ReadFile(sslrootcert)
if err != nil {
return err
sslinline := o["sslinline"]

var cert []byte
if sslinline == "true" {
// // Clear out this param, in case it were to be sent to the PostgreSQL server by mistake
o["sslrootcert"] = ""
cert = []byte(sslrootcert)
} else {
var err error
cert, err = ioutil.ReadFile(sslrootcert)
if err != nil {
return err
}
}

if !tlsConf.RootCAs.AppendCertsFromPEM(cert) {
4 changes: 2 additions & 2 deletions url.go
Original file line number Diff line number Diff line change
@@ -40,10 +40,10 @@ func ParseURL(url string) (string, error) {
}

var kvs []string
escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`)
escaper := strings.NewReplacer(`'`, `\'`, `\`, `\\`)
accrue := func(k, v string) {
if v != "" {
kvs = append(kvs, k+"="+escaper.Replace(v))
kvs = append(kvs, k+"='"+escaper.Replace(v)+"'")
}
}

6 changes: 3 additions & 3 deletions url_test.go
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ import (
)

func TestSimpleParseURL(t *testing.T) {
expected := "host=hostname.remote"
expected := "host='hostname.remote'"
str, err := ParseURL("postgres://hostname.remote")
if err != nil {
t.Fatal(err)
@@ -17,7 +17,7 @@ func TestSimpleParseURL(t *testing.T) {
}

func TestIPv6LoopbackParseURL(t *testing.T) {
expected := "host=::1 port=1234"
expected := "host='::1' port='1234'"
str, err := ParseURL("postgres://[::1]:1234")
if err != nil {
t.Fatal(err)
@@ -29,7 +29,7 @@ func TestIPv6LoopbackParseURL(t *testing.T) {
}

func TestFullParseURL(t *testing.T) {
expected := `dbname=database host=hostname.remote password=top\ secret port=1234 user=username`
expected := `dbname='database' host='hostname.remote' password='top secret' port='1234' user='username'`
str, err := ParseURL("postgres://username:top%20secret@hostname.remote:1234/database")
if err != nil {
t.Fatal(err)