github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/lib/pq/ssl_test.go (about) 1 package pq 2 3 // This file contains SSL tests 4 5 import ( 6 _ "crypto/sha256" 7 "crypto/x509" 8 "database/sql" 9 "fmt" 10 "os" 11 "path/filepath" 12 "testing" 13 ) 14 15 func maybeSkipSSLTests(t *testing.T) { 16 // Require some special variables for testing certificates 17 if os.Getenv("PQSSLCERTTEST_PATH") == "" { 18 t.Skip("PQSSLCERTTEST_PATH not set, skipping SSL tests") 19 } 20 21 value := os.Getenv("PQGOSSLTESTS") 22 if value == "" || value == "0" { 23 t.Skip("PQGOSSLTESTS not enabled, skipping SSL tests") 24 } else if value != "1" { 25 t.Fatalf("unexpected value %q for PQGOSSLTESTS", value) 26 } 27 } 28 29 func openSSLConn(t *testing.T, conninfo string) (*sql.DB, error) { 30 db, err := openTestConnConninfo(conninfo) 31 if err != nil { 32 // should never fail 33 t.Fatal(err) 34 } 35 // Do something with the connection to see whether it's working or not. 36 tx, err := db.Begin() 37 if err == nil { 38 return db, tx.Rollback() 39 } 40 _ = db.Close() 41 return nil, err 42 } 43 44 func checkSSLSetup(t *testing.T, conninfo string) { 45 db, err := openSSLConn(t, conninfo) 46 if err == nil { 47 db.Close() 48 t.Fatalf("expected error with conninfo=%q", conninfo) 49 } 50 } 51 52 // Connect over SSL and run a simple query to test the basics 53 func TestSSLConnection(t *testing.T) { 54 maybeSkipSSLTests(t) 55 // Environment sanity check: should fail without SSL 56 checkSSLSetup(t, "sslmode=disable user=pqgossltest") 57 58 db, err := openSSLConn(t, "sslmode=require user=pqgossltest") 59 if err != nil { 60 t.Fatal(err) 61 } 62 rows, err := db.Query("SELECT 1") 63 if err != nil { 64 t.Fatal(err) 65 } 66 rows.Close() 67 } 68 69 // Test sslmode=verify-full 70 func TestSSLVerifyFull(t *testing.T) { 71 maybeSkipSSLTests(t) 72 // Environment sanity check: should fail without SSL 73 checkSSLSetup(t, "sslmode=disable user=pqgossltest") 74 75 // Not OK according to the system CA 76 _, err := openSSLConn(t, "host=postgres sslmode=verify-full user=pqgossltest") 77 if err == nil { 78 t.Fatal("expected error") 79 } 80 _, ok := err.(x509.UnknownAuthorityError) 81 if !ok { 82 t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err) 83 } 84 85 rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") 86 rootCert := "sslrootcert=" + rootCertPath + " " 87 // No match on Common Name 88 _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-full user=pqgossltest") 89 if err == nil { 90 t.Fatal("expected error") 91 } 92 _, ok = err.(x509.HostnameError) 93 if !ok { 94 t.Fatalf("expected x509.HostnameError, got %#+v", err) 95 } 96 // OK 97 _, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-full user=pqgossltest") 98 if err != nil { 99 t.Fatal(err) 100 } 101 } 102 103 // Test sslmode=verify-ca 104 func TestSSLVerifyCA(t *testing.T) { 105 maybeSkipSSLTests(t) 106 // Environment sanity check: should fail without SSL 107 checkSSLSetup(t, "sslmode=disable user=pqgossltest") 108 109 // Not OK according to the system CA 110 _, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest") 111 if err == nil { 112 t.Fatal("expected error") 113 } 114 _, ok := err.(x509.UnknownAuthorityError) 115 if !ok { 116 t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err) 117 } 118 119 rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") 120 rootCert := "sslrootcert=" + rootCertPath + " " 121 // No match on Common Name, but that's OK 122 _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-ca user=pqgossltest") 123 if err != nil { 124 t.Fatal(err) 125 } 126 // Everything OK 127 _, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-ca user=pqgossltest") 128 if err != nil { 129 t.Fatal(err) 130 } 131 } 132 133 func getCertConninfo(t *testing.T, source string) string { 134 var sslkey string 135 var sslcert string 136 137 certpath := os.Getenv("PQSSLCERTTEST_PATH") 138 139 switch source { 140 case "missingkey": 141 sslkey = "/tmp/filedoesnotexist" 142 sslcert = filepath.Join(certpath, "postgresql.crt") 143 case "missingcert": 144 sslkey = filepath.Join(certpath, "postgresql.key") 145 sslcert = "/tmp/filedoesnotexist" 146 case "certtwice": 147 sslkey = filepath.Join(certpath, "postgresql.crt") 148 sslcert = filepath.Join(certpath, "postgresql.crt") 149 case "valid": 150 sslkey = filepath.Join(certpath, "postgresql.key") 151 sslcert = filepath.Join(certpath, "postgresql.crt") 152 default: 153 t.Fatalf("invalid source %q", source) 154 } 155 return fmt.Sprintf("sslmode=require user=pqgosslcert sslkey=%s sslcert=%s", sslkey, sslcert) 156 } 157 158 // Authenticate over SSL using client certificates 159 func TestSSLClientCertificates(t *testing.T) { 160 maybeSkipSSLTests(t) 161 // Environment sanity check: should fail without SSL 162 checkSSLSetup(t, "sslmode=disable user=pqgossltest") 163 164 // Should also fail without a valid certificate 165 db, err := openSSLConn(t, "sslmode=require user=pqgosslcert") 166 if err == nil { 167 db.Close() 168 t.Fatal("expected error") 169 } 170 pge, ok := err.(*Error) 171 if !ok { 172 t.Fatal("expected pq.Error") 173 } 174 if pge.Code.Name() != "invalid_authorization_specification" { 175 t.Fatalf("unexpected error code %q", pge.Code.Name()) 176 } 177 178 // Should work 179 db, err = openSSLConn(t, getCertConninfo(t, "valid")) 180 if err != nil { 181 t.Fatal(err) 182 } 183 rows, err := db.Query("SELECT 1") 184 if err != nil { 185 t.Fatal(err) 186 } 187 rows.Close() 188 } 189 190 // Test errors with ssl certificates 191 func TestSSLClientCertificatesMissingFiles(t *testing.T) { 192 maybeSkipSSLTests(t) 193 // Environment sanity check: should fail without SSL 194 checkSSLSetup(t, "sslmode=disable user=pqgossltest") 195 196 // Key missing, should fail 197 _, err := openSSLConn(t, getCertConninfo(t, "missingkey")) 198 if err == nil { 199 t.Fatal("expected error") 200 } 201 // should be a PathError 202 _, ok := err.(*os.PathError) 203 if !ok { 204 t.Fatalf("expected PathError, got %#+v", err) 205 } 206 207 // Cert missing, should fail 208 _, err = openSSLConn(t, getCertConninfo(t, "missingcert")) 209 if err == nil { 210 t.Fatal("expected error") 211 } 212 // should be a PathError 213 _, ok = err.(*os.PathError) 214 if !ok { 215 t.Fatalf("expected PathError, got %#+v", err) 216 } 217 218 // Key has wrong permissions, should fail 219 _, err = openSSLConn(t, getCertConninfo(t, "certtwice")) 220 if err == nil { 221 t.Fatal("expected error") 222 } 223 if err != ErrSSLKeyHasWorldPermissions { 224 t.Fatalf("expected ErrSSLKeyHasWorldPermissions, got %#+v", err) 225 } 226 }